From e8c6af9b60a36f362a349bbeeeea3288e336c68b Mon Sep 17 00:00:00 2001 From: Robert Cornea Date: Thu, 4 Jun 2026 11:36:57 +0300 Subject: [PATCH] LG-53877 LG-53880 - update file type documentation --- .../writing_guidelines.md | 0 api/projectautomation/.manifest | 1 + ...ion.Settings.TranslationMemorySettings.yml | 31 +++ api/translationmemory/.manifest | 2 +- ...onMemory.TranslationUnitBcmInformation.yml | 34 ++-- .../about_the_example_bil_format.md | 81 ++++---- .../add_a_resources_file_bil.md | 18 +- .../add_a_resources_file_native.md | 19 +- .../adding_a_preview_controller.md | 106 ++++------ .../adding_a_preview_ui_control.md | 25 ++- .../adding_context_information.md | 62 +++--- .../adding_the_file_type_component_builder.md | 22 +- .../adding_the_file_writer_class.md | 118 ++++------- .../adding_the_text_extractor_class.md | 75 ++----- ...ppendix_real_time_preview_for_xml_files.md | 28 ++- .../applying_character_formatting.md | 32 ++- ...ng_the_segment_pair_confirmation_levels.md | 41 ++-- ..._adding_the_file_type_component_builder.md | 30 ++- .../bil_implementing_the_file_sniffer.md | 113 +++++------ .../filetypesupport/bilingual_file_parser.md | 108 +++++----- .../filetypesupport/bilingual_file_sniffer.md | 14 +- ...bilingual_file_type_plugin_introduction.md | 31 +-- .../filetypesupport/bilingual_file_writer.md | 60 +++--- .../bilingual_filter_ui_settings.md | 12 +- .../build_the_file_type_plug_in.md | 82 ++++---- ...reate_a_bilingual_verifier_introduction.md | 28 ++- .../create_a_native_verifier_introduction.md | 30 +-- .../create_a_new_bil_project.md | 36 ++-- .../create_a_new_native_project.md | 35 ++-- .../create_new_file_type_component_builder.md | 56 ++--- .../creating_a_native_file_tweaker.md | 106 +++++----- ...ting_a_new_assembly_for_the_settings_ui.md | 51 ++--- .../creating_a_new_bil_project.md | 46 ++--- .../filetypesupport/creating_a_new_project.md | 27 ++- .../filetypesupport/creating_projects.md | 21 +- ...difying_the_file_type_component_builder.md | 27 ++- .../enhance_plugin_introduction.md | 14 +- ...the_file_parser_to_process_the_settings.md | 55 ++--- .../enhancing_the_preview_file_writer.md | 76 +++---- ...ng_existing_file_type_component_builder.md | 67 +++--- .../extending_the_configuration_options.md | 87 +++----- .../extending_the_filter_component_builder.md | 31 ++- .../filetypesupport/extracting_comments.md | 48 ++--- .../filetypesupport/file_type_settings.md | 49 +++-- .../file_type_support_overview.md | 65 +++--- .../filetypesupport/filter_ui_settings.md | 34 ++-- .../generating_the_paragraph_units.md | 85 +++----- .../global_verifier_introduction.md | 5 +- .../handling_tags_during_segmentation.md | 38 ++-- .../filetypesupport/how_translators_work.md | 76 +++---- .../filetypesupport/images/TTXandITD.jpg | Bin 91757 -> 0 bytes .../filetypesupport/imarkupdatavisitor.md | 60 +++--- .../implement_the_ui_controller_class_bil.md | 104 ++++------ ...mplement_the_ui_controller_class_native.md | 105 ++++------ .../implement_the_user_interface_bil.md | 108 ++++------ .../implement_the_user_interface_native.md | 85 +++----- .../implement_the_verification_logic_bil.md | 191 +++++++----------- ...implement_the_verification_logic_native.md | 123 ++++------- .../implementing_an_external_file_preview.md | 26 ++- .../implementing_quickinsert_functionality.md | 72 +++---- .../implementing_the_file_parser.md | 159 +++++++-------- .../implementing_the_file_sniffer.md | 55 ++--- .../implementing_the_file_writer.md | 92 ++++----- .../implementing_the_preview_writer.md | 76 ++----- .../implementing_the_settings_ui.md | 91 +++------ .../implementing_the_ui_controller_class.md | 106 +++++----- .../initializing_the_file_type_manager.md | 33 +-- .../internal_preview_introduction.md | 23 +-- .../loading_and_saving_settings.md | 137 +++++-------- .../loading_and_saving_the_settings_bil.md | 181 ++++++----------- .../loading_and_saving_the_settings_native.md | 117 +++-------- .../locking_specific_strings.md | 93 +-------- ...mapping_the_segment_confirmation_levels.md | 58 +----- apiconcepts/filetypesupport/merging_files.md | 24 ++- .../moving_files_between_machines.md | 26 ++- .../filetypesupport/native_file_tweakers.md | 42 ++-- .../opening_a_document_for_translation.md | 46 +++-- .../opening_the_file_for_parsing.md | 85 +++----- .../outputting_all_comments.md | 165 +++------------ .../outputting_segment_pairs.md | 96 +++------ apiconcepts/filetypesupport/overview.md | 58 ++++-- .../overview_of_the_billingual_api.md | 53 +++-- .../overview_of_the_native_api.md | 74 ++++--- .../filetypesupport/previewing_files.md | 36 ++-- .../processing_inline_formatting.md | 86 +++----- .../filetypesupport/processing_inline_tags.md | 34 ++-- .../processing_native_formats_introduction.md | 32 +-- .../processing_placeholder_tags.md | 42 ++-- .../putting_it_all_together.md | 50 +---- .../filetypesupport/reporting_problems.md | 142 ++++++------- .../filetypesupport/sample_projects.md | 10 +- .../saving_to_different_file_types.md | 15 -- .../filetypesupport/segmentation_hints.md | 7 +- .../filetypesupport/settings_page_example.md | 41 ++-- ...difying_the_file_type_component_builder.md | 51 +++-- .../sub_content_component_builder.md | 17 +- .../filetypesupport/sub_content_overview.md | 33 +-- .../filetypesupport/tag_display_modes.md | 48 ++--- .../filetypesupport/text_formatting.md | 15 +- .../filetypesupport/the_file_context.md | 32 ++- .../filetypesupport/the_file_parser.md | 53 ++--- .../filetypesupport/the_file_sniffer.md | 33 +-- .../the_file_type_plug_in_life_cycle.md | 55 ++--- .../filetypesupport/the_file_writer.md | 60 +++--- .../the_filter_component_builder.md | 92 ++++----- .../filetypesupport/the_filter_preview.md | 42 ++-- .../filetypesupport/the_main_parser.md | 11 +- .../filetypesupport/the_main_writer.md | 7 +- .../filetypesupport/the_resources_file.md | 9 +- .../filetypesupport/the_sub_content_parser.md | 33 +-- .../filetypesupport/the_sub_content_writer.md | 9 +- .../filetypesupport/used_terminology.md | 46 ++--- .../user_communication_through_messaging.md | 54 ++--- .../using_context_information.md | 39 ++-- .../filetypesupport/using_quickinserts.md | 39 ++-- .../filetypesupport/verifying_files.md | 29 +-- .../what_a_file_type_plugin_must_do.md | 54 ++--- ...n_you_do_with_the_file_type_support_sdk.md | 11 - .../what_is_the_verification_framework.md | 47 ++--- apiconcepts/toc.yml | 56 +++-- 120 files changed, 2685 insertions(+), 3887 deletions(-) rename writing_guidelines.md => .github/writing_guidelines.md (100%) delete mode 100644 apiconcepts/filetypesupport/images/TTXandITD.jpg delete mode 100644 apiconcepts/filetypesupport/saving_to_different_file_types.md delete mode 100644 apiconcepts/filetypesupport/what_can_you_do_with_the_file_type_support_sdk.md diff --git a/writing_guidelines.md b/.github/writing_guidelines.md similarity index 100% rename from writing_guidelines.md rename to .github/writing_guidelines.md diff --git a/api/projectautomation/.manifest b/api/projectautomation/.manifest index 19c1335c28..092e2cec53 100644 --- a/api/projectautomation/.manifest +++ b/api/projectautomation/.manifest @@ -857,6 +857,7 @@ "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.HardFilter": "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml", "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.LongDatePattern": "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml", "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.LongTimePattern": "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml", + "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments": "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml", "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MeasurementsAutoLocalizationEnabled": "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml", "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MeasurementsFormattingCustomSpace": "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml", "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MeasurementsFormattingMode": "Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml", diff --git a/api/projectautomation/Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml b/api/projectautomation/Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml index 4b8118b3d5..ab5002b08e 100644 --- a/api/projectautomation/Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml +++ b/api/projectautomation/Sdl.ProjectAutomation.Settings.TranslationMemorySettings.yml @@ -31,6 +31,7 @@ items: - Sdl.ProjectAutomation.Settings.TranslationMemorySettings.HardFilter - Sdl.ProjectAutomation.Settings.TranslationMemorySettings.LongDatePattern - Sdl.ProjectAutomation.Settings.TranslationMemorySettings.LongTimePattern + - Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments - Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MeasurementsAutoLocalizationEnabled - Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MeasurementsFormattingCustomSpace - Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MeasurementsFormattingMode @@ -693,6 +694,29 @@ items: type: Sdl.Core.Settings.Setting{System.Int32} content.vb: Public ReadOnly Property ConcordanceMaximumResults As Setting(Of Integer) overload: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.ConcordanceMaximumResults* +- uid: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments + commentId: P:Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments + id: MaximumContextSegments + parent: Sdl.ProjectAutomation.Settings.TranslationMemorySettings + langs: + - csharp + - vb + name: MaximumContextSegments + nameWithType: TranslationMemorySettings.MaximumContextSegments + fullName: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments + type: Property + assemblies: + - Sdl.ProjectAutomation.Settings + namespace: Sdl.ProjectAutomation.Settings + summary: 'Gets or sets the maximum number of context segments. Default: 1.' + example: [] + syntax: + content: public Setting MaximumContextSegments { get; } + parameters: [] + return: + type: Sdl.Core.Settings.Setting{System.Int32} + content.vb: Public ReadOnly Property MaximumContextSegments As Setting(Of Integer) + overload: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments* - uid: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.StopSearchingWhenResultsFound commentId: P:Sdl.ProjectAutomation.Settings.TranslationMemorySettings.StopSearchingWhenResultsFound id: StopSearchingWhenResultsFound @@ -3013,6 +3037,13 @@ references: name: ConcordanceMaximumResults nameWithType: TranslationMemorySettings.ConcordanceMaximumResults fullName: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.ConcordanceMaximumResults +- uid: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments* + commentId: Overload:Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments + isExternal: true + href: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.html#Sdl_ProjectAutomation_Settings_TranslationMemorySettings_MaximumContextSegments + name: MaximumContextSegments + nameWithType: TranslationMemorySettings.MaximumContextSegments + fullName: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.MaximumContextSegments - uid: Sdl.ProjectAutomation.Settings.TranslationMemorySettings.StopSearchingWhenResultsFound* commentId: Overload:Sdl.ProjectAutomation.Settings.TranslationMemorySettings.StopSearchingWhenResultsFound isExternal: true diff --git a/api/translationmemory/.manifest b/api/translationmemory/.manifest index 82a4898bd9..a88c511d37 100644 --- a/api/translationmemory/.manifest +++ b/api/translationmemory/.manifest @@ -3062,7 +3062,7 @@ "Sdl.LanguagePlatform.TranslationMemory.TranslationUnit.Validate": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnit.yml", "Sdl.LanguagePlatform.TranslationMemory.TranslationUnit.Validate(Sdl.LanguagePlatform.Core.Segment.ValidationMode)": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnit.yml", "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml", - "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.Int32)": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml", + "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.String)": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml", "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.Id": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml", "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.SegmentNumber": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml", "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.Title": "Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml", diff --git a/api/translationmemory/Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml b/api/translationmemory/Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml index 03661b3be2..a0413ef82e 100644 --- a/api/translationmemory/Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml +++ b/api/translationmemory/Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.yml @@ -5,7 +5,7 @@ items: id: TranslationUnitBcmInformation parent: Sdl.LanguagePlatform.TranslationMemory children: - - Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.Int32) + - Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.String) - Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.Id - Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.SegmentNumber - Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.Title @@ -38,16 +38,16 @@ items: - System.Object.GetHashCode - System.Object.GetType - System.Object.MemberwiseClone -- uid: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.Int32) - commentId: M:Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.Int32) - id: '#ctor(System.Guid,System.Int32,System.String,System.Int32)' +- uid: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.String) + commentId: M:Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor(System.Guid,System.Int32,System.String,System.String) + id: '#ctor(System.Guid,System.Int32,System.String,System.String)' parent: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation langs: - csharp - vb - name: TranslationUnitBcmInformation(Guid, int, string, int) - nameWithType: TranslationUnitBcmInformation.TranslationUnitBcmInformation(Guid, int, string, int) - fullName: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.TranslationUnitBcmInformation(System.Guid, int, string, int) + name: TranslationUnitBcmInformation(Guid, int, string, string) + nameWithType: TranslationUnitBcmInformation.TranslationUnitBcmInformation(Guid, int, string, string) + fullName: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.TranslationUnitBcmInformation(System.Guid, int, string, string) type: Constructor assemblies: - Sdl.LanguagePlatform.TranslationMemory @@ -55,7 +55,7 @@ items: summary: '' example: [] syntax: - content: public TranslationUnitBcmInformation(Guid id, int version, string title, int segmentNumber) + content: public TranslationUnitBcmInformation(Guid id, int version, string title, string segmentNumber) parameters: - id: id type: System.Guid @@ -64,12 +64,12 @@ items: - id: title type: System.String - id: segmentNumber - type: System.Int32 - content.vb: Public Sub New(id As Guid, version As Integer, title As String, segmentNumber As Integer) + type: System.String + content.vb: Public Sub New(id As Guid, version As Integer, title As String, segmentNumber As String) overload: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor* - nameWithType.vb: TranslationUnitBcmInformation.New(Guid, Integer, String, Integer) - fullName.vb: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.New(System.Guid, Integer, String, Integer) - name.vb: New(Guid, Integer, String, Integer) + nameWithType.vb: TranslationUnitBcmInformation.New(Guid, Integer, String, String) + fullName.vb: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.New(System.Guid, Integer, String, String) + name.vb: New(Guid, Integer, String, String) - uid: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.Id commentId: P:Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.Id id: Id @@ -156,14 +156,14 @@ items: content: >- [DataMember] - public int SegmentNumber { get; set; } + public string SegmentNumber { get; set; } parameters: [] return: - type: System.Int32 + type: System.String content.vb: >- - Public Property SegmentNumber As Integer + Public Property SegmentNumber As String overload: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.SegmentNumber* attributes: - type: System.Runtime.Serialization.DataMemberAttribute @@ -480,7 +480,7 @@ references: - uid: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor* commentId: Overload:Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.#ctor isExternal: true - href: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.html#Sdl_LanguagePlatform_TranslationMemory_TranslationUnitBcmInformation__ctor_System_Guid_System_Int32_System_String_System_Int32_ + href: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.html#Sdl_LanguagePlatform_TranslationMemory_TranslationUnitBcmInformation__ctor_System_Guid_System_Int32_System_String_System_String_ name: TranslationUnitBcmInformation nameWithType: TranslationUnitBcmInformation.TranslationUnitBcmInformation fullName: Sdl.LanguagePlatform.TranslationMemory.TranslationUnitBcmInformation.TranslationUnitBcmInformation diff --git a/apiconcepts/filetypesupport/about_the_example_bil_format.md b/apiconcepts/filetypesupport/about_the_example_bil_format.md index 5209a1c007..db51f450bb 100644 --- a/apiconcepts/filetypesupport/about_the_example_bil_format.md +++ b/apiconcepts/filetypesupport/about_the_example_bil_format.md @@ -1,14 +1,12 @@ -About the Example BIL Format -=== +# About the Example BIL Format -In order to demonstrate the main features that can be used when developing a bilingual file type plug-in, we have created an example format with the extension **.bil* (from now on BIL). This file type is not used in any 3rd party application. It is a fictitious document format, which was created only for this SDK sample project. +To demonstrate the main features of a bilingual file type plug-in, this sample uses a fictitious format with the `.bil` extension. This format does not belong to a third-party application. It exists only for this SDK sample. -Format Description --- +## Format Description -BIL is custom a XML based format which looks as shown below: +BIL is a custom XML-based format, as shown in the following example: -# [Xml](#tab/tabid-1) +# [XML](#tab/tabid-1) ```xml @@ -22,43 +20,42 @@ BIL is custom a XML based format which looks as shown below: Leistungsmerkmale - This segment was translated using web translator. + This segment was translated using web translator. + ``` -*** - The BIL format contains the following elements: -* ```bilingualdocument```: The root element, in which the source and the target languages are specified within element attributes. -* ```unit```: Acts as the container for the source and the target content. Each unit element is identified by the unique value of the id attribute. Also the unit element contains a status attribute, which defines whether the current unit is, for example, new or an exact match. -* ```source```: Contains one seg element, which stores the actual source segment content. -* ```target```: Can contain a seg element for storing the target content. The target element can be empty if no target segment is available. -* ```seg```: Encloses the actual source or target content. Segment content may be enclosed in inline tags such as *< b >*, *< i >*, etc. -* ```type```: Contains additional information on the type of unit, e.g. heading, paragraph, footnote, etc. -* ```comment```: contains a comment related to a unit (if applicable). To keep this example as simple as possible, let us assume that a unit can only have one comment. +- `bilingualdocument`: The root element. Its attributes specify the source and target languages. +- `unit`: The container for the source and target content. Each `unit` has a unique `id` attribute and a `status` attribute that identifies the translation state, such as `new` or `exact`. +- `source`: Contains a `seg` element that stores the source segment content. +- `target`: Can contain a `seg` element that stores the target content. The `target` element can remain empty when no target segment is available. +- `seg`: Encloses the source or target content. Segment content can contain inline tags such as `` and ``. +- `type`: Contains additional information about the unit type, such as heading, paragraph, or footnote. +- `comment`: Contains a comment for a unit, when applicable. For simplicity, this example assumes that each unit has at most one comment. -What the Sample File Type Plug-in Must Do --- +## What the Sample File Type Plug-in Must Do -Your file type plug-in needs to fulfill the following requirements: +The sample file type plug-in must: -* Generate an SDLXliff file from a given BIL document -* Traverse the BIL file and extract all units; each unit shall represent a paragraph in the translation editor of Var:ProductName -* Expose all source segments for translation -* Expose all target segments (if available) -* Markup inline tags such as *< b>* as tag pairs within the segments and apply the appropriate display formatting -* Generate (untranslatable) contexts from the type attribute values (e.g. heading) -* Map the BIL unit status values to the appropriate confirmation levels found in the intermediary format used by Var:ProductName (i.e. SDLXliff), e.g. translated, draft, approved, etc. -* Back conversion, i.e. writing back the content from the intermediary document (SDLXliff)into a target BIL file +- Generate an SDLXLIFF file from a BIL document. +- Traverse the BIL file and extract all units so that each unit appears as a paragraph in the Var:ProductName translation editor. +- Expose all source segments for translation. +- Expose all target segments, when available. +- Mark up inline tags such as `` as tag pairs within segments and apply the correct display formatting. +- Generate untranslatable contexts from `type` attribute values such as `heading`. +- Map BIL `status` values to the appropriate confirmation levels in the intermediary format used by Var:ProductName, such as `translated`, `draft`, and `approved`. +- Support back-conversion by writing content from the intermediary SDLXLIFF document to a target BIL file. -When developing the sample file type plug-in we fill primarily focus on extraction (file parser) and generation (file writer) as well as ways of mapping BIL features to SDLXliff features. We will not implement additional functionality such as QuickInsert, user-configurable settings, or document preview, as this is already covered in the chapter on developing a native file type plug-in. +This sample focuses on extraction through the file parser, generation through the file writer, and mapping BIL features to SDLXLIFF features. It does not implement additional functionality such as QuickInsert, user-configurable settings, or document preview, because the chapter on developing a native file type plug-in already covers those topics. -Example Document -Below you see an example of a more comprehensive document, which you can use for testing your BIL file type plug-in: +## Example Document -# [Xml](#tab/tabid-2) +The following example shows a more comprehensive document that you can use to test your BIL file type plug-in: + +# [XML](#tab/tabid-2) ```xml @@ -73,7 +70,7 @@ Below you see an example of a more comprehensive document, which you can use for Leistungsmerkmale - This segment was translated using web translator. + This segment was translated using web translator. @@ -95,15 +92,15 @@ Below you see an example of a more comprehensive document, which you can use for The largest translation supply chain in the world - + Trados Studio is the world’s most popular translation software with over 170,000 users. - - + + @@ -111,22 +108,20 @@ Below you see an example of a more comprehensive document, which you can use for Dedicated translation environment to handle almost any file type - + Easily open and start working on the widest range of file formats, from the latest Microsoft Office files to XML, from HTML to InDesign. - - -This is the original comment + + + This is the original comment ``` -*** - >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/add_a_resources_file_bil.md b/apiconcepts/filetypesupport/add_a_resources_file_bil.md index 44fcb5ea4d..f1999c3d8a 100644 --- a/apiconcepts/filetypesupport/add_a_resources_file_bil.md +++ b/apiconcepts/filetypesupport/add_a_resources_file_bil.md @@ -1,22 +1,22 @@ -Add a Resources File -=== +# Add a Resources File -In this step, you add a resource file to the project, which contains the message strings that will be shown to end user in the UI of Var:ProductName. +In this step, you add a resource file to the project that contains the message strings shown to end users in the Var:ProductName UI. -Our verification plug-in will output error messages whenever a problem has been identified. It is, of course, not required, but recommended to enter the message strings in a resources file. Start by adding a resources file (named e.g. **Resources.resx**) to your project. The resources file should contain the following strings: +The verification plug-in outputs error messages when it identifies a problem. Although a resources file is not required, it is the recommended way to store these message strings. Start by adding a resources file, for example **Resources.resx**, to your project. -* A message stating the maximum word count (as set through the plug-in user interface) and the number of words that were actually found in the target segment. -* The name of the plug-in that has detected the problem. This is important, as a user might run several verifiers at the same time (e.g. the QA Checker, the Generic Tag Verification, and our sample WordArt checker). By including the name of the verification plug-in that generated an error, the user will know from verifier a particular message came. In the **Messages** window of Var:ProductName users can also sort error messages by plug-in name. +Include the following strings in the resources file: +- A message that states the maximum word count configured in the plug-in UI and the number of words actually found in the target segment. +- The name of the plug-in that detected the problem. This helps when users run several verifiers at the same time, such as the QA Checker, Generic Tag Verification, and the sample WordArt checker. By including the verifier name, users can identify which plug-in generated the error. In the **Messages** window of Var:ProductName, users can also sort error messages by plug-in name. -Below you see an example of a verification message as it might be thrown by our sample plug-in: +The following example shows a verification message that the sample plug-in might generate: ![Error_Message_Length_Worksheet_Exceeded](images/Error_Message_Length_Worksheet_Exceeded.jpg) -The resources file will look as shown below: +The resources file should look like this: ![WordArtVerifierResources](images/WordArtVerifierResources.jpg) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/add_a_resources_file_native.md b/apiconcepts/filetypesupport/add_a_resources_file_native.md index 2c51ee03ca..5fed6e2439 100644 --- a/apiconcepts/filetypesupport/add_a_resources_file_native.md +++ b/apiconcepts/filetypesupport/add_a_resources_file_native.md @@ -1,22 +1,21 @@ -Add a Resources File -=== +# Add a Resources File -In this step you add a resources file for storing the strings, which users will see in the user interface of Var:ProductName. +In this step, you add a resources file that stores the strings shown to users in the Var:ProductName user interface. -Add a resource file to your project and call it e.g. ```StringResources.resx```. To properly inform the user of any length limit violations, a message should display the following information: +Add a resources file to your project, for example `StringResources.resx`. To clearly report length-limit violations, include message strings that provide the following information: -* The actual length limit as specified in the **maxlength** attribute. -* The target segment text that was found to be longer than the specified length limit. -* The name of the plug-in that has detected the problem. This is important, as a user might run several verifiers at the same time (e.g. the QA Checker, the Generic Tag Verification, and our length checker sample implementation). By including the name of the verification plug-in that generated an error, the user will know from verifier a particular message came. In the **Messages** window of Var:ProductName users can also sort error messages by plug-in name. +- The actual length limit specified in the `maxlength` attribute. +- The target segment text that exceeds the specified length limit. +- The name of the plug-in that detected the problem. This helps when users run several verifiers at the same time, such as the QA Checker, Generic Tag Verification, and the sample length checker. By including the verifier name, users can identify which plug-in generated the error. In the **Messages** window of Var:ProductName, users can also sort error messages by plug-in name. -Therefore, your resources file should look as shown below: +The resources file should look like this: ![ResourcesXMLChecker](images/ResourcesXMLChecker.jpg) -Below you see an example of an error message as it might be generated by our sample plug-in: +The following example shows an error message that the sample plug-in might generate: ![Error_Message_Maxlength_XML_Exceeded](images/Error_Message_Maxlength_XML_Exceeded.jpg) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/adding_a_preview_controller.md b/apiconcepts/filetypesupport/adding_a_preview_controller.md index 0174466b0a..5d6e61d2fb 100644 --- a/apiconcepts/filetypesupport/adding_a_preview_controller.md +++ b/apiconcepts/filetypesupport/adding_a_preview_controller.md @@ -1,30 +1,27 @@ -Adding a Preview Controller -=== +# Adding a preview controller -Last, you need to implement a class for controlling the actual preview control element, which you added in the previous step. +The last step is to implement a class that controls the preview control element that you added in the previous step. -Add a Preview Controller Class --- +## Add a preview controller class -The preview control element alone is not sufficient for implementing the real-time preview functionality. You also need to add a class that controls the preview UI, which you can call e.g. **InternalPreviewController.cs**. This class is used to catch events such as the user clicking the **Refresh** button in the preview window, the user clicking a segment, scrolling to a segment, confirming a segment in the editor, etc. When those events are caught by the controller class, it triggers the corresponding functions that have been implemented in the preview control UI (see chapter [Adding a Preview UI Control](adding_a_preview_ui_control.md)). +The preview control element alone cannot provide the real-time preview functionality. You also need a class that controls the preview UI, for example **InternalPreviewController.cs**. This class handles events such as clicking the **Refresh** button, selecting a segment, scrolling to a segment, and confirming a segment in the editor. In response, it calls the functions implemented in the preview control UI. See [Adding a Preview UI Control](adding_a_preview_ui_control.md). -The preview controller class needs to use the following namespaces: +The preview controller class uses the following namespaces: -* **Sdl.FileTypeSupport.Framework** -* **Sdl.FileTypeSupport.Framework.NativeApi** -* **Sdl.FileTypeSupport.Framework.IntegrationApi** +- **Sdl.FileTypeSupport.Framework** +- **Sdl.FileTypeSupport.Framework.NativeApi** +- **Sdl.FileTypeSupport.Framework.IntegrationApi** -The class must then implement the following interfaces: +The class must implement the following interfaces: -* [ISingleFilePreviewControl](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISingleFilePreviewControl.yml): Provides access to the preview file, which is generated in the user's temporary files folder. -* [INavigablePreview](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.INavigablePreview.yml): Users can navigate to particular segments in the preview window. This interface provides the functionality to control what should happen when a user, e.g. clicks a particular segment in the preview. -* [IPreviewUpdatedViaRefresh](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IPreviewUpdatedViaRefresh.yml): Users can click a **Refresh** button in the preview control. This interface implements functions for controlling the preview behavior before and after a refresh operation. -* `IDisposable`: The preview generates a physical preview file in the user's temporary folder under **SDLTempFileManager**. This temporary file needs to be deleted when the preview is closed or when the user, for example, exits the application. This interface provides the functionality for disposing of the preview file when it is no longer required. +- [ISingleFilePreviewControl](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISingleFilePreviewControl.yml): Provides access to the preview file generated in the user's temporary files folder. +- [INavigablePreview](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.INavigablePreview.yml): Lets users navigate to segments in the preview window and defines what happens when they do. +- [IPreviewUpdatedViaRefresh](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IPreviewUpdatedViaRefresh.yml): Defines what happens before and after users click **Refresh** in the preview control. +- `IDisposable`: Disposes of the physical preview file stored temporarily under **SDLTempFileManager** when the preview closes or the application exits. -Declare the Global Members --- +## Declare the global members -First, declare the following global class members. Create a `_control` object for controlling the actual preview UI and other members used to store the file id and to determine whether the preview file has already been opened or not. +Start by declaring the following class members. Create a `_control` object for the preview UI. Add members to store the file ID and track whether the preview file is already open. # [C#](#tab/tabid-1) ```cs @@ -36,12 +33,10 @@ FileId _fileId; // the actual file ID // so we know if we should close it during a Refresh() bool _isFileOpen = false; ``` -*** -Initialize the Preview Control UI --- +## Initialize the preview control UI -Then add the following members to initialize the preview control and to properly dispose of it, e.g. when the preview or the application is closed by the user. +Next, add the following members to initialize the preview control and dispose of it correctly when the preview or application closes. # [C#](#tab/tabid-2) ```cs @@ -61,12 +56,10 @@ public InternalPreviewController() Dispose(false); } ``` -*** -Implement the Members of the Abstract Preview Control Interface --- +## Implement the members of the abstract preview control interface -The [IAbstractPreviewControl](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IAbstractPreviewControl.yml) interface provides the functionality that allows you to control, e.g. what happens when the preview control is refreshed. Add the following members to your preview controller class: +The [IAbstractPreviewControl](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IAbstractPreviewControl.yml) interface lets you control preview behavior, including refresh operations. Add the following members to your preview controller class: # [C#](#tab/tabid-3) ```cs @@ -112,12 +105,10 @@ public void Refresh() _isFileOpen = true; } ``` -*** -Provide Access to the Temporary Preview File --- +## Provide access to the temporary preview file -Add the following member, which provides programmatic access to the physical preview file, which is going to be temporarily generated on the user's hard disk: +Add the following member to provide programmatic access to the physical preview file that is generated temporarily on the user's machine: # [C#](#tab/tabid-4) ```cs @@ -130,12 +121,10 @@ public TempFileManager PreviewFile set; } ``` -*** -Implement the Preview Document Navigation --- +## Implement the preview document navigation -In the next step, implement the following members of the [INavigablePreview](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.INavigablePreview.yml) interface. These functions control what should happen when the user, for example, scrolls to or selects a particular segment in the preview control. +Next, implement the following members of the [INavigablePreview](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.INavigablePreview.yml) interface. These functions control what happens when the user scrolls to or selects a segment in the preview control. # [C#](#tab/tabid-5) ```cs @@ -174,12 +163,10 @@ public virtual void OnSegmentSelected(object sender, SegmentSelectedEventArgs ar } } ``` -*** -Dispose of the Preview File --- +## Dispose of the preview file -Add the following members of the `IDisposable` interface, which takes care of cleaning up and removing the temporary preview files, e.g. after the application is closed by the user: +Add the following members of the `IDisposable` interface to clean up and remove temporary preview files, for example after the application closes: # [C#](#tab/tabid-6) ```cs @@ -219,12 +206,10 @@ protected virtual void Dispose(bool disposing) } } ``` -*** -Implement the Refresh Functionality --- +## Implement the refresh functionality -Add the following members of the [IPreviewUpdatedViaRefresh](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IPreviewUpdatedViaRefresh.yml) interface, which provides the functionality to control what happens when the user refreshes the preview control: +Add the following members of the [IPreviewUpdatedViaRefresh](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IPreviewUpdatedViaRefresh.yml) interface to control what happens when the user refreshes the preview control: # [C#](#tab/tabid-7) ```cs @@ -249,12 +234,12 @@ public TempFileManager TargetFilePath set; } ``` -*** -Register the Preview Controller in the File Type Component Builder ---- +## Register the preview controller in the file type component builder -Do not forget to register the preview controller (i.e. NOT the actual user control item) in the File Type Component Builder as follows. You can add this object below the control used for the static preview (see chapter [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md)). Note that the **id** of the object corresponds to the name of the preview set that you added previously (see chapter [Modifying the File Type Component Builder](dynamic_modifying_the_file_type_component_builder.md)) and must be preceded by a ***PreviewControl_*** prefix to be properly recognized. +Register the preview controller, not the user control itself, in the File Type Component Builder as follows. You can add this object below the control used for the static preview. See [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md). + +The object **id** must match the preview set name that you added earlier. See [Modifying the File Type Component Builder](dynamic_modifying_the_file_type_component_builder.md). It must also start with the **PreviewControl_** prefix. # [C#](#tab/tabid-8) ```cs @@ -285,12 +270,10 @@ public virtual IAbstractPreviewControl BuildPreviewControl(string name) } } ``` -*** -Putting it All Together --- +## Put it all together -All put together, the preview controller class will look as shown below: +The complete preview controller class looks like this: # [C#](#tab/tabid-9) ```cs @@ -303,7 +286,6 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview { class InternalPreviewController : ISingleFilePreviewControl, INavigablePreview, IPreviewUpdatedViaRefresh, IDisposable { - #region "global" InternalPreviewControl _control; // the actual control object private bool disposed = false; // used for properly disposing of the control FileId _fileId; // the actual file ID @@ -311,9 +293,7 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview // indicates whether a file has already been opened in the preview, // so we know if we should close it during a Refresh() bool _isFileOpen = false; - #endregion - #region "init" /// /// initialize the preview controller and preview control /// @@ -329,10 +309,8 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview { Dispose(false); } - #endregion - #region "IAbstractPreviewControl Members" /// /// return a preview control /// @@ -374,9 +352,7 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview _isFileOpen = true; } - #endregion - #region "Temp File Manager" /// /// access to the temporary preview file /// @@ -387,10 +363,6 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview } - #endregion - - - #region "INavigablePreview Members" /// /// reference to the current segment /// @@ -425,9 +397,7 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview SegmentSelected(sender, args); } } - #endregion - #region "IDisposable Members" /// /// deletes the preview file, if it exists. /// @@ -463,9 +433,7 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview } } } - #endregion - #region "IPreviewUpdatedViaRefresh Members" public void AfterFileRefresh() { Refresh(); @@ -486,11 +454,15 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview get; set; } - #endregion } } ``` -*** + +## See also + +- [Adding a Preview UI Control](adding_a_preview_ui_control.md) +- [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md) +- [Modifying the File Type Component Builder](dynamic_modifying_the_file_type_component_builder.md) >[!NOTE] diff --git a/apiconcepts/filetypesupport/adding_a_preview_ui_control.md b/apiconcepts/filetypesupport/adding_a_preview_ui_control.md index 49575ec39e..41c1e19793 100644 --- a/apiconcepts/filetypesupport/adding_a_preview_ui_control.md +++ b/apiconcepts/filetypesupport/adding_a_preview_ui_control.md @@ -1,19 +1,18 @@ -Adding a Preview UI Control -=== +# Adding a preview UI control -For displaying the document preview your filter requires a suitable control element. +Your filter needs a control that can display the document preview. -Add a Web Browser Control --- +## Add a web browser control -When implementing the static internal preview, we simply leveraged the built-in Web browser control of Var:ProductName (see [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md)). Depending on the native file format that needs to be displayed, a different control might be required. For example, for DOC files Var:ProductName uses a Microsoft Word Viewer control. In this exercise, we are (once again) going to use a Web browser control. However, this time we will not leverage the built-in Web browser control, since we would like to demonstrate how to add and configure a custom control element. +The static internal preview uses the built-in web browser control in Var:ProductName. See [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md). Other native file formats may require different controls. For example, DOC files use a Microsoft Word Viewer control. -Start by adding a user control called e.g. **InternalPreviewControl.cs** to your project. From the Visual Studio toolbox add a Web browser control, and assign the name `webBrowserControl` to it. +This sample uses a web browser control again, but this time it adds and configures a custom control instead of reusing the built-in one. -Implement the Preview Control Functionality --- +Start by adding a user control such as **InternalPreviewControl.cs** to your project. Then add a web browser control from the Visual Studio toolbox and name it `webBrowserControl`. -For your preview control to be able to respond to events such as the user clicking a segment in the editor, scrolling to a segment, etc., your control needs to implement the following code: +## Implement the preview control functionality + +To respond to events such as clicking a segment in the editor or scrolling to a segment, implement the following code in your preview control: # [C#](#tab/tabid-1) ```cs @@ -200,7 +199,11 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview } } ``` -*** + +## See also + +- [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md) +- [Adding a Preview Controller](adding_a_preview_controller.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/adding_context_information.md b/apiconcepts/filetypesupport/adding_context_information.md index 0281f165f7..74537f43e9 100644 --- a/apiconcepts/filetypesupport/adding_context_information.md +++ b/apiconcepts/filetypesupport/adding_context_information.md @@ -1,42 +1,37 @@ -Adding Context Information -=== +# Adding Context Information -In this chapter you will learn how to extract helpful context information from a given BIL file. +This section explains how to extract useful context information from a BIL file. -About Contexts --- +## About Contexts -For the translators it is often useful to know whether a given segment occurs in a headline, paragraph, etc. Units in the BIL sample format may contain a `type` element, which indicates the context of a `unit` element, e.g.: +Translators often need to know whether a segment appears in a heading, paragraph, or another document element. In the BIL sample format, a `unit` can contain a `type` element that identifies this context: ```xml ``` +Var:ProductName can display this information in a column next to the target segments. In this section, you enhance the parser so that Var:ProductName shows the `type` element information in the editor. -Var:ProductName can display such information in a column next to the target segments. In this chapter we want to enhance our parser to show the information from the type element in the editor of Var:ProductName. - -Below you see an example of how the context information can be displayed in the translation environment. Each context cell contains a display code, which is the abbreviated form of the full context, e.g. **T** for **Topic**. You may also assign different colors for each context type as a visual aid for the translator. +The following example shows how the translation environment can display context information. Each context cell contains a display code, which abbreviates the full context, for example **T** for **Topic**. You can also assign a different color to each context type to help translators identify them quickly. ![BilContext](images/BilContext.jpg) +The API lets you create custom context information from the BIL file or use standard context types. These standard types cover common document elements such as titles, paragraphs, and text boxes. -The API allows you to either create custom context information using, for example, the information from the BIL file, or you can draw from a collection of standard context types. The API offers various standard types to cover a large variety of possible elements that may occur in a document such as title, paragraph, text box, etc. - -To keep things simple let us consider only three mapping scenarios. The table below lists the BIL type values, which should be mapped to the corresponding standard context types offered by the API: +For simplicity, this example uses three mapping scenarios. The following table lists the BIL type values and the corresponding standard context types: -| BIL Type | Standard Context Type | +| BIL Type | Standard Context Type | |-----------|-----------------------| -| Heading | Topic | -| Box | Text Box | +| Heading | Topic | +| Box | Text Box | -For our implementation, let us assume the following: If a unit in the BIL file does not have a type element, then the standard context type **paragraph** should be used. +For this implementation, assume that when a unit in the BIL file does not contain a `type` element, the parser uses the standard **paragraph** context type. -Apart from the `type` element content we can also use the context information to store the unique id of the units found in the BIL file. The unit element contains an id attribute, which stores the id value. This id should not be shown to the end user, as it is not relevant for the translation. However, it should be included somewhere in the intermediary (SDLXliff) file, so that the writer class (which we will implement later) can reference it when generating the target BIL file (see [Adding the File Writer Class](adding_the_file_writer_class.md)). Within the context properties (but not only there) you can include metadata, which is not visible to the user, but is stored physically in the intermediary (SDLXliff) file. +In addition to the `type` element, you can use context information to store the unique ID of each unit in the BIL file. The `unit` element contains this value in its `id` attribute. Do not display this ID to end users because it is not relevant during translation. Instead, store it in the intermediary SDLXLIFF file so that the writer class can reference it later when it generates the target BIL file. For more information, see [Adding the File Writer Class](adding_the_file_writer_class.md). You can store this kind of hidden information as metadata in the context properties. -Note that adding metadata is not limited to contexts. You can apply metadata to various types of instances such as inline tags, structure tags, placeables, etc. +You can add metadata to more than contexts. You can also apply it to inline tags, structure tags, placeables, and other objects. -Extend the Helper Function for Creating Paragraph Units --- +## Extend the Helper Function for Creating Paragraph Units First, add the following to the `CreateParagraphUnit()` helper function: @@ -53,12 +48,10 @@ if(xmlUnit.SelectSingleNode("type/@spec")!=null) paragraphUnit.Properties.Contexts = CreateContext("Paragraph", id); } ``` -*** -The above condition determines whether a `type` element is available in the first place. If this is the case, the value from the spec attribute is passed to another helper function (which we will add later), which returns the appropriate context properties object. If not, the additional helper function needs to generate a standard paragraph context properties object. -Second, we determine the value of the id attribute of the current `unit` element, and pass it to the separate helper function. +This condition checks whether a `type` element is available. If it is, the code passes the `spec` attribute value to a helper function that returns the appropriate context properties object. If the `type` element is missing, the helper function creates a standard paragraph context instead. The code also reads the `id` attribute from the current `unit` element and passes it to the same helper function. -The full `CreateParagraphUnit()` helper function should look as shown below: +The complete `CreateParagraphUnit()` helper function should look like this: # [C#](#tab/tabid-2) ```cs @@ -85,7 +78,6 @@ private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) paragraphUnit.Target.Add(trgSegment); } - #region "context" // create paragraph unit context string id = xmlUnit.SelectSingleNode("./@id").InnerText; if(xmlUnit.SelectSingleNode("type/@spec")!=null) @@ -96,31 +88,25 @@ private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) } else { paragraphUnit.Properties.Contexts = CreateContext("Paragraph", id); } - #endregion - - #region "comments" // extract comment (if applicable) if(xmlUnit.SelectSingleNode("comment")!=null) { paragraphUnit.Properties.Comments = CreateComment(xmlUnit.SelectSingleNode("comment").InnerText); } - #endregion return paragraphUnit; } ``` -*** -Add the Helper Function to Create the Context Properties --- +## Add the Helper Function to Create the Context Properties -Before you implement the new context helper function, add the `System.Drawing` library as a reference to your project. This facilitates the task of assigning different background colors to the various context types, which makes distinguishing the contexts easer for the end user. +Before you implement the new context helper function, add a reference to the `System.Drawing` library. This library lets you assign different background colors to context types, which makes them easier for end users to distinguish. -Also, you need to add the following namespace to your class, which provides access to the standard context types that the API offers: `Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi` +Also add the following namespace to your class so that you can access the standard context types that the API provides: `Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi` -This function uses the properties factory to create a context properties object as well as a context information object. By default, we assign the context type [Paragraph](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.StandardContextTypes.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_StandardContextTypes_Paragraph) value from the [StandardContextTypes](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.StandardContextTypes.yml) collection. Also, we set the [ContextPurpose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml) to [Information](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields). This means that the context information is purely for information, and not for TM matching purposes. The function than uses a switch statement to map the value from the spec attribute of the `type` element to the corresponding standard context type and assigns a background colour. +This function uses the properties factory to create a context properties object and a context information object. By default, it assigns the [Paragraph](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.StandardContextTypes.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_StandardContextTypes_Paragraph) value from the [StandardContextTypes](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.StandardContextTypes.yml) collection. It also sets [ContextPurpose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml) to [Information](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields), which means the context helps users but does not affect TM matching. The function then uses a switch statement to map the `spec` attribute value from the `type` element to the corresponding standard context type and assigns a background color. -The second context info (`contextID`) that is added to the context properties object contains the unit id. Remember that this information is not supposed to be visible to the end user. That is why we add it through the [MetaData](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml#Sdl_FileTypeSupport_Framework_NativeApi_IMetaDataContainer_MetaData) property. In this case, the `Add()` method requires two string parameters: the key (i.e. the field name) and the actual value. +The second context info object (`contextID`) that is added to the context properties contains the unit ID. This information should remain hidden from end users, so the code stores it through the [MetaData](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml#Sdl_FileTypeSupport_Framework_NativeApi_IMetaDataContainer_MetaData) property. In this case, the `Add()` method requires two string parameters: the key and the value. # [C#](#tab/tabid-3) ```cs @@ -159,8 +145,6 @@ private IContextProperties CreateContext(string spec, string unitID) return contextProperties; } ``` -*** - >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/adding_the_file_type_component_builder.md b/apiconcepts/filetypesupport/adding_the_file_type_component_builder.md index 9ad207b067..79c6db24de 100644 --- a/apiconcepts/filetypesupport/adding_the_file_type_component_builder.md +++ b/apiconcepts/filetypesupport/adding_the_file_type_component_builder.md @@ -1,22 +1,22 @@ -Adding the File Type Component Builder -=== +# Adding the File Type Component Builder -Add the File Type Component Builder to your project. This is the implementation of the interface [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). and that is used to define the new file type plug-in, so that it can be used in Var:ProductName. +Add a File Type Component Builder to your project. Implement [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) to define your file type plug-in so that Var:ProductName can load it. -Add the File Type Information -Your File Type Component Builder needs to contain information such as the file type plug-in version number, the extension of the files that this file type plug-in applies to, etc. This kind of information is what end users see in the **Options** dialog box of Var:ProductName under **File Types**. +## Add the file type information -The implementation of [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) also reference each file type plug-in component, e.g. the file sniffer class, the file parser class, etc. If you fail to reference a file type plug-in component in the file type definition, the component cannot be used in Var:ProductName. The File Type Component Builder thereby fully reflects the component structure of the file type plug-in. At this point, we would like to underline the importance of sub-dividing your file type plug-in into distinct components, as each component performs a different, even if sometimes similar, task. +Your File Type Component Builder defines metadata such as the plug-in version and the file extensions that the plug-in supports. Var:ProductName displays this information in **Options** under **File Types**. -Let us start by adding the general file type information to the implementation of [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) as shown below: +Your implementation of [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) also registers each file type plug-in component, such as the file sniffer class and the file parser class. If you do not register a component in the file type definition, Var:ProductName cannot use it. The File Type Component Builder reflects the structure of your file type plug-in, so keep the components distinct and focused. + +Start by adding the general file type information to your implementation of [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml): # [C#](#tab/tabid-1) ```cs /// /// Returns a file type information object. /// -/// The will pass "" as the name for this parameter -/// an SimpleText file type information object +/// The passes an empty string for this parameter. +/// A SimpleText file type information object. public virtual IFileTypeInformation BuildFileTypeInformation(string name) { var info = this.FileTypeManager.BuildFileTypeInformation(); @@ -41,11 +41,11 @@ public virtual IFileTypeInformation BuildFileTypeInformation(string name) ``` *** -After adding the file type information above, the corresponding file type plug-in would be shown to the end user in the **Options** dialog box as illustrated below. Your example file type plug-in will be listed under **File Types**, however, of course it does not implement any functionality yet. Below you see an example of how the information entered in the File Type Component Builder is presented to the user through the UI of Var:ProductName: +After you add this information, Var:ProductName lists the file type plug-in in **Options** under **File Types**, as shown in the following example. At this stage, the example plug-in appears in the UI but does not provide any functionality yet. ![SimpleTextFilesProperties](images/SimpleTextFilesProperties.jpg) -Of course, a File Type Component Builder file is a lot more comprehensive than what is shown here. As we develop the actual file type plug-in components, we will add the corresponding component references to the File Type Component Builder file step-by-step. +The File Type Component Builder contains more than the metadata shown here. As you develop the file type plug-in components, add the corresponding component references to the File Type Component Builder step by step. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/adding_the_file_writer_class.md b/apiconcepts/filetypesupport/adding_the_file_writer_class.md index 7af182ae52..4c914eef14 100644 --- a/apiconcepts/filetypesupport/adding_the_file_writer_class.md +++ b/apiconcepts/filetypesupport/adding_the_file_writer_class.md @@ -1,27 +1,25 @@ -Adding the File Writer Class -=== +# Adding the File Writer Class -In this chapter you will learn how to implement the file writer component, which generates the target BIL file from an intermediary (SDLXliff) document. +This section explains how to implement the file writer component that generates a target BIL file from an intermediary SDLXLIFF document. -Add the Writer Class --- +## Add the Writer Class -Start by adding a class called e.g. **BilWriter.cs** to your project. Like the parser component, this class uses the following namespaces of the bilingual and the native APIs: +Start by adding a class such as **BilWriter.cs** to your project. Like the parser component, this class uses the following namespaces from the bilingual and native APIs: -* Sdl.FileTypeSupport.Framework.BilingualApi -* Sdl.FileTypeSupport.Framework.NativeApi +- `Sdl.FileTypeSupport.Framework.BilingualApi` +- `Sdl.FileTypeSupport.Framework.NativeApi` -Since the writer is going to generate XML target files, you should also add the ```System.Xml``` namespace. -The class needs to be derived from the following class and interfaces: +Because the writer generates XML target files, add the `System.Xml` namespace as well. -* [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) -* [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) -* [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml) +Derive the class from the following base class and interfaces: -Add the Members for the File Properties --- +- [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) +- [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) +- [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml) -Start by adding the following global class members: +## Add the Members for the File Properties + +Start by adding the following class members: # [C#](#tab/tabid-1) ```cs @@ -29,15 +27,14 @@ private IPersistentFileConversionProperties _originalFileProperties; private INativeOutputFileProperties _nativeFileProperties; private XmlDocument _targetFile; ``` -*** -The ```_originalFileProperties``` object provides access to the source BIL file. From this object you can retrieve any information on the original file (e.g. the original source language, encoding, file path and name, etc.). +The `_originalFileProperties` object provides access to the source BIL file. You can use it to retrieve information about the original file, such as the source language, encoding, file path, and file name. -The ```_nativeFileProperties``` object provides access to the (proposed) target BIL file information - most importantly to the target file output path. +The `_nativeFileProperties` object provides access to the proposed target BIL file information, especially the target output path. -The ```_targetFile``` object is an XML DOM object that we will use for constructing the actual target BIL file output later. +The `_targetFile` object is an XML DOM object that you will use later to construct the target BIL output file. -Now add the following (required) members of the [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml) interface to initialize the objects that provide access to the original file information and the native output file information: +Next, add the required members of the [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml) interface to initialize the objects that provide access to the original file information and the native output file information: # [C#](#tab/tabid-2) ```cs @@ -51,9 +48,8 @@ public void SetOutputProperties(INativeOutputFileProperties properties) _nativeFileProperties = properties; } ``` -*** -Next, add the members of the [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) interface. Start with the ```SetFileProperties()``` method, which we use to load the original BIL document into our ```_targetFile``` DOM object: +Then add the members of the [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) interface. Start with the `SetFileProperties()` method, which loads the original BIL document into the `_targetFile` DOM object: # [C#](#tab/tabid-3) ```cs @@ -63,17 +59,13 @@ public void SetFileProperties(IFileProperties fileInfo) _targetFile.Load(_originalFileProperties.OriginalFilePath); } -#region "initialize" public void Initialize(IDocumentProperties documentInfo) { } -#endregion ``` -*** - -Then add the ```Initialize()``` method, which we leave empty for the moment. We will use this member later (see [Adding the Text Extractor Class](adding_the_text_extractor_class.md)) to create another object through with we will access the segment content: +For now, leave the `Initialize()` method empty. In a later step, you will use this member to create another object that provides access to the segment content. For more information, see [Adding the Text Extractor Class](adding_the_text_extractor_class.md). # [C#](#tab/tabid-4) ```cs @@ -82,13 +74,9 @@ public void Initialize(IDocumentProperties documentInfo) } ``` -*** - - -Create the Paragraph Units in the Output File --- +## Create the Paragraph Units in the Output File -Add another (required) member of the [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) interface. This method is used to loop through the paragraph units of the intermediary (SDLXliff) file and output the unit elements to our target BIL file. We will leave this method empty for the moment and fill it with the required application logic later. +Add another required member of the [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) interface. This method loops through the paragraph units of the intermediary SDLXLIFF file and writes the corresponding `unit` elements to the target BIL file. Leave the method empty for now and add the implementation later. # [C#](#tab/tabid-5) ```cs @@ -97,14 +85,11 @@ public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) } ``` -*** +## Save and Complete the Process -Save and Complete the Process --- +Add the following required members of the [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) interface. These members complete the native output file and the overall writing process. Use the `FileComplete()` method to save the target BIL file and set the DOM object to `null`. -Add the following (required) members of the [IBilingualWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualWriter.yml) interface, which are used to complete the native output file and to complete the entire parsing process. We will use the ```FileComplete()``` method to save the target BIL file and to set the DOM object to ```null```. - -We will leave the ```Complete()``` method empty, as it is not required in this simple implementation. You may wonder why the interface offers two (seemingly similar) members, i.e. one to complete a file, another one to complete the writing process. Remember that Var:ProductName allows you to merge several native files into one big intermediary document, from which the individual target files can be generated when saving the document as target. You can use these two methods, for example, to first generate each native target file individually and then to conclude the entire writing process. +Leave the `Complete()` method empty because this simple implementation does not require it. The interface offers both methods because Var:ProductName can merge several native files into a single intermediary document. You can use `FileComplete()` to finish each native target file individually and `Complete()` to conclude the overall writing process. # [C#](#tab/tabid-6) ```cs @@ -119,12 +104,9 @@ public void Complete() } ``` -*** - -Putting it All Together --- +## Putting It All Together -The skeleton writer class looks as shown below. This is the minimum amount of code required to build a file type plug-in with a writer component. You could actually build your project now, and the file writer will even produce a target BIL file. However, this target file will do nothing more than output the content of the original BIL document, which is embedded in the intermediary document as a dependency file. In the following chapters you will learn how to generate a BIL target file that includes the actual translations and comments entered in Var:ProductName by manipulating the target file DOM object programmatically. +The following skeleton writer class contains the minimum code required to build a file type plug-in with a writer component. At this stage, you can build the project and the writer can produce a target BIL file. However, that file only outputs the content of the original BIL document, which the intermediary document embeds as a dependency file. In the following sections, you will learn how to manipulate the target file DOM object so that the generated BIL file includes the translations and comments entered in Var:ProductName. # [C#](#tab/tabid-7) ```cs @@ -137,13 +119,10 @@ namespace Sdk.Snippets.Bilingual { class BilWriter : AbstractBilingualFileTypeComponent, IBilingualWriter, INativeOutputSettingsAware { - #region "global" private IPersistentFileConversionProperties _originalFileProperties; private INativeOutputFileProperties _nativeFileProperties; private XmlDocument _targetFile; - #endregion - #region "INativeOutputSettingsAware members" public void GetProposedOutputFileInfo(IPersistentFileConversionProperties fileProperties, IOutputFileInfo proposedFileInfo) { _originalFileProperties = fileProperties; @@ -153,36 +132,23 @@ namespace Sdk.Snippets.Bilingual { _nativeFileProperties = properties; } - #endregion - - - #region "IBilingualWriter members" - - #region "load file" public void SetFileProperties(IFileProperties fileInfo) { _targetFile = new XmlDocument(); _targetFile.Load(_originalFileProperties.OriginalFilePath); } - #region "initialize" public void Initialize(IDocumentProperties documentInfo) { } - #endregion - - #endregion - #region "paragraphs" public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) { } - #endregion - #region "save file and complete" public void FileComplete() { _targetFile.Save(_nativeFileProperties.OutputFilePath); @@ -193,27 +159,18 @@ namespace Sdk.Snippets.Bilingual { } - #endregion - - #endregion - - #region Implementation of IDisposable public void Dispose() { throw new NotImplementedException(); } - - #endregion } } ``` -*** -Reference the Component in the File Type Component Builder --- +## Reference the Component in the File Type Component Builder -Do not forget to reference the file writer class by adding the following code to the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation: +Reference the file writer class by adding the following code to the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation: # [C#](#tab/tabid-8) ```cs @@ -222,19 +179,14 @@ public IFileGenerator BuildFileGenerator(string name) return this.FileTypeManager.BuildFileGenerator(new BilWriter()); } ``` -*** - -See Also --- -[Adding the Text Extractor Class](adding_the_text_extractor_class.md) - -[Generating the Paragraph Units](generating_the_paragraph_units.md) - -[Mapping the Segment Confirmation Levels](mapping_the_segment_confirmation_levels.md) +## See Also -[Outputting all Comments](outputting_all_comments.md) +- [Adding the Text Extractor Class](adding_the_text_extractor_class.md) +- [Generating the Paragraph Units](generating_the_paragraph_units.md) +- [Mapping the Segment Confirmation Levels](mapping_the_segment_confirmation_levels.md) +- [Outputting all Comments](outputting_all_comments.md) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/adding_the_text_extractor_class.md b/apiconcepts/filetypesupport/adding_the_text_extractor_class.md index 067ac6b925..75cd10a697 100644 --- a/apiconcepts/filetypesupport/adding_the_text_extractor_class.md +++ b/apiconcepts/filetypesupport/adding_the_text_extractor_class.md @@ -1,19 +1,16 @@ -Adding the Text Extractor Class -=== +# Adding the Text Extractor Class -In this chapter you will learn how to add a separate class that helps you access segment content such as text and tag pairs. +This section explains how to add a helper class that gives you access to segment content such as text and tag pairs. -Add the Text Extractor Helper Class --- +## Add the Text Extractor Helper Class -A segment is like a container that can include (apart from 'normal' text) various types of elements such as tag pairs, placeholders, comments, locked content, etc. In our simple implementation we would like to focus on how to retrieve text and tag pairs only. These are the elements that are most commonly found in a segment. +A segment acts as a container for several element types, including text, tag pairs, placeholders, comments, and locked content. This simple implementation focuses only on text and tag pairs because they are the most common elements in a segment. -Add a new class to your project, called e.g. **BilTextExtractor.cs**. Since this class is also used to handle bilingual content, it needs to use the namespace S```dl.FileTypeSupport.Framework.BilingualApi```. The class must implement the interface [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml), which provides access to the markup data elements found in a segment. +Add a new class to your project, for example **BilTextExtractor.cs**. Because this class handles bilingual content, add the `Sdl.FileTypeSupport.Framework.BilingualApi` namespace. The class must implement the [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) interface, which provides access to the markup data elements in a segment. -Generate the Plain Text --- +## Generate the Plain Text -Now add the following members to your class: +Add the following members to your class: # [C#](#tab/tabid-1) ```cs @@ -30,9 +27,8 @@ public string GetPlainText(ISegment segment) return PlainText.ToString(); } ``` -*** -The public ```GetPlainText()``` helper function will be called later from the file writer. The writer will pass the current segment object to this method, which will then generate and return text as well as tag pairs. The ```GetPlainText()``` function calls the ```VisitChildren()``` helper function, which loops through all items in a segment markup container such as text and tags: +The public `GetPlainText()` helper function is called later from the file writer. The writer passes the current segment object to this method, which returns the segment text together with any tag pairs. `GetPlainText()` calls the `VisitChildren()` helper function, which loops through all items in a segment markup container such as text and tags: # [C#](#tab/tabid-2) ```cs @@ -44,16 +40,13 @@ private void VisitChildren(IAbstractMarkupDataContainer container) } } ``` -*** +## Collect the Markup Container Items -Collect the Markup Container Items --- +For each element type that can appear in a segment markup container, add a separate member as required by the [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) interface. To keep this example simple, process only text and tag pairs. In a later section, you will extend this class to return comments that were added during translation. -For each type of element that you can encounter in a segment (markup) container you need to add a separate member as required by the [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) interface. To keep this example as simple as possible, we will process only text and tag pairs. In one of the following chapters we will enhance this class to also return any comments that were added during the translation process. +Leave the remaining members for locked content, placeholders, and other element types empty. -We will leave all other members for retrieving e.g. locked content, placeholders, etc. empty. - -The ```VistText()``` method adds a text object to the ```PlainText``` streambuilder, which is then also returned to the file writer class: +The `VisitText()` method adds a text object to the `PlainText` string builder, which the file writer later receives: # [C#](#tab/tabid-3) ```cs @@ -62,9 +55,8 @@ public void VisitText(IText text) PlainText.Append(text.Properties.Text); } ``` -*** -The [VisitTagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitTagPair_Sdl_FileTypeSupport_Framework_BilingualApi_ITagPair_) method, which is a member of the [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) interface, adds a tag pair object to the ```PlainText``` streambuilder, which is then returned to the file writer class: +The [VisitTagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitTagPair_Sdl_FileTypeSupport_Framework_BilingualApi_ITagPair_) method adds a tag pair to the `PlainText` string builder, which the file writer then uses: # [C#](#tab/tabid-4) ```cs @@ -75,9 +67,8 @@ public void VisitTagPair(ITagPair tagPair) PlainText.Append(""); } ``` -*** -We leave the [VisitCommentMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitCommentMarker_Sdl_FileTypeSupport_Framework_BilingualApi_ICommentMarker_) method empty for the moment, and will come back to it later: +Leave the [VisitCommentMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitCommentMarker_Sdl_FileTypeSupport_Framework_BilingualApi_ICommentMarker_) method empty for now. You will return to it later: # [C#](#tab/tabid-5) ```cs @@ -86,9 +77,8 @@ public void VisitCommentMarker(ICommentMarker commentMarker) } ``` -*** -All other required interface members will be left empty in our sample implementation: +Leave the other required interface members empty in this sample implementation: # [C#](#tab/tabid-6) ```cs @@ -122,12 +112,10 @@ public void VisitRevisionMarker(IRevisionMarker revisionMarker) } ``` -**** -Putting it All Together --- +## Putting It All Together -The complete text extractor class should now look as shown below: +The complete text extractor class should now look like this: # [C#](#tab/tabid-7) ```cs @@ -138,7 +126,6 @@ namespace Sdk.Snippets.Bilingual { class BilTextExtractor : IMarkupDataVisitor { - #region "plain text" internal StringBuilder PlainText { get; @@ -151,10 +138,8 @@ namespace Sdk.Snippets.Bilingual VisitChildren(segment); return PlainText.ToString(); } - #endregion // loops through all sub items of the container (IMarkupDataContainer) - #region "loop" private void VisitChildren(IAbstractMarkupDataContainer container) { foreach (var item in container) @@ -162,35 +147,25 @@ namespace Sdk.Snippets.Bilingual item.AcceptVisitor(this); } } - #endregion - - #region IMarkupDataVisitor Members - #region "text" public void VisitText(IText text) { PlainText.Append(text.Properties.Text); } - #endregion - #region "tagpairs" public void VisitTagPair(ITagPair tagPair) { PlainText.Append("<" + tagPair.StartTagProperties.TagContent + ">"); VisitChildren(tagPair); PlainText.Append(""); } - #endregion - #region "comments" public void VisitCommentMarker(ICommentMarker commentMarker) { } - #endregion - #region "left empty" public void VisitSegment(ISegment segment) { VisitChildren(segment); @@ -220,23 +195,15 @@ namespace Sdk.Snippets.Bilingual { } - #endregion - - #endregion } } ``` -*** - -See Also --- - - -[Adding the File Writer Class](adding_the_file_writer_class.md) +## See Also -[Generating the Paragraph Units](generating_the_paragraph_units.md) +- [Adding the File Writer Class](adding_the_file_writer_class.md) +- [Generating the Paragraph Units](generating_the_paragraph_units.md) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/appendix_real_time_preview_for_xml_files.md b/apiconcepts/filetypesupport/appendix_real_time_preview_for_xml_files.md index 13f032566b..c60f3ea9c8 100644 --- a/apiconcepts/filetypesupport/appendix_real_time_preview_for_xml_files.md +++ b/apiconcepts/filetypesupport/appendix_real_time_preview_for_xml_files.md @@ -1,15 +1,15 @@ -Appendix: Real-time Preview for XML Files -=== +# Appendix: Real-time preview for XML files -This chapter explains how to use XSLT stylesheets to implement a real-time preview for custom XML documents. +This article explains how to use XSLT stylesheets to implement a real-time preview for custom XML documents. -Real-time Preview for XML Through XSTL -For XML files it is not necessary to develop a real-time preview component. All you need to do is to add a suitable XSLT stylesheet into your custom XML file type settings. The stylesheet code will then embedded in the settings bundle for your custom XML file type. +## Real-time preview for XML through XSLT -The SDK sample folder **Realtime XML Preview** contains a set of sample files: +For XML files, you do not need to develop a real-time preview component. Instead, add a suitable XSLT stylesheet to your custom XML file type settings. Var:ProductName then embeds the stylesheet code in the settings bundle for your custom XML file type. -* A sample XML source file to translate (**sample.xml**) -* An XSL stylesheet (**stylesheet.xsl**) +The SDK sample folder **Realtime XML Preview** contains the following files: + +- A sample XML source file to translate (**sample.xml**) +- An XSL stylesheet (**stylesheet.xsl**) The sample XML file looks as shown below: @@ -36,9 +36,8 @@ The sample XML file looks as shown below: ``` -*** -Below you find the corresponding XSL code: +The following XSL code transforms the sample XML file: # [Xml](#tab/tabid-1) ```xml @@ -75,18 +74,17 @@ Below you find the corresponding XSL code: ``` -*** -The XSL stylesheet can be embedded in settings bundle through the File Type Manager user interface by selecting the corresponding file type and by adding the XSL file in the **Preview** section as shown in the following illustration: +You can embed the XSL stylesheet in the settings bundle through the File Type Manager UI. Select the corresponding file type, then add the XSL file in the **Preview** section, as shown in the following illustration: ![add_stylesheet](images/add_stylesheet.jpg) -Once the XSL file has been embedded in the settings bundle, the real-time preview can be called during translation (see example below): +After you embed the XSL file in the settings bundle, you can open the real-time preview during translation: ![XML_preview](images/XML_preview.jpg) - Settings bundle for your custom XML file type can be of course exported (as **.sdlftsettings*) and distributed to other users. +You can also export the settings bundle for your custom XML file type as **.sdlftsettings** and distribute it to other users. - >[!NOTE] +>[!NOTE] > > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/applying_character_formatting.md b/apiconcepts/filetypesupport/applying_character_formatting.md index de285015fb..fc100c27fe 100644 --- a/apiconcepts/filetypesupport/applying_character_formatting.md +++ b/apiconcepts/filetypesupport/applying_character_formatting.md @@ -1,16 +1,14 @@ -Applying Character Formatting -=== +# Applying Character Formatting -In this chapter you will learn how to enrich the editor display in with character display formatting. +This section explains how to enrich the editor display in Var:ProductName with character formatting. -Apply Character Formatting --- +## Apply Character Formatting -From the inline tags that our sample format is using it is easy to decide which type of character formatting to apply. Display formatting in an intermediary (SDLXliff) document is strictly speaking not necessary and has no impact on the actual BIL target file. It can be optionally applied for convenience reasons, at it usually helps translators to see the actual character formatting. It is also possible to hide inline tags, and just show the display formatting that they define. That way translators can apply the formatting to the corresponding strings in the target segments instead of transferring tags. +The inline tags in the sample format make it easy to determine which character formatting to apply. Display formatting in an intermediary SDLXLIFF document is optional and does not affect the generated BIL target file. However, it helps translators recognize the intended formatting more easily. You can also hide inline tags and show only the formatting they represent. This approach lets translators apply formatting to the corresponding text in the target segment instead of transferring tags. -First, you need to add the following namespace to your parser class: using ```Sdl.FileTypeSupport.Framework.Formatting```. +First, add the following namespace to your parser class: `Sdl.FileTypeSupport.Framework.Formatting`. -Then you enhance your `CreateTagPair()` helper function, so that it not only generates tag pairs, but that is also applies the appropriate formatting at the same time. Through a ``switch`` statement you can then select the appropriate formatting based on the name of the element node: +Then update the `CreateTagPair()` helper function so that it generates tag pairs and applies the appropriate formatting at the same time. Use a `switch` statement to select the correct formatting based on the element name: # [C#](#tab/tabid-1) ```cs @@ -32,9 +30,8 @@ switch (item.Name) break; } ``` -*** -The complete ```CreateTagPair()``` helper function should look as shown below. Note that by setting the [CanHide](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractInlineTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractInlineTagProperties_CanHide) to True the actual tags are by default not displayed in . However, allows users to toggle on/off the tag display at runtime. +The complete `CreateTagPair()` helper function should look like this. When you set [CanHide](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractInlineTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractInlineTagProperties_CanHide) to `true`, Var:ProductName hides the actual tags by default. Users can still toggle tag display at runtime. # [C#](#tab/tabid-2) ```cs @@ -42,7 +39,7 @@ private ITagPair CreateTagPair(XmlNode item) { // create the start and the end tag IStartTagProperties startTag = PropertiesFactory.CreateStartTagProperties(item.Name); - #region "formatting" + // apply character formatting to the start tag IFormattingGroup formattingGroup = PropertiesFactory.FormattingItemFactory.CreateFormatting(); startTag.Formatting = new FormattingGroup(); @@ -61,7 +58,6 @@ private ITagPair CreateTagPair(XmlNode item) break; } startTag.Formatting = formattingGroup; - #endregion startTag.DisplayText=item.Name; startTag.CanHide = true; @@ -78,22 +74,20 @@ private ITagPair CreateTagPair(XmlNode item) return tagPair; } ``` -*** -When you build your project at this point, the intermediary (SDLXliff) document should look as shown below: +When you build the project at this point, the intermediary SDLXLIFF document should look like this: ![BilTagOff](images/BilTagOff.jpg) -The following shows what the intermediary (SDLXliff) file looks like when the user decides to display inline tags at runtime: +The following example shows the intermediary SDLXLIFF file when users choose to display inline tags at runtime: ![BilTagOn](images/BilTagOn.jpg) -See Also --- +## See Also -[Processing Inline Tags](processing_inline_tags.md) +- [Processing Inline Tags](processing_inline_tags.md) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/applying_the_segment_pair_confirmation_levels.md b/apiconcepts/filetypesupport/applying_the_segment_pair_confirmation_levels.md index 37bd613054..2d278dc7f0 100644 --- a/apiconcepts/filetypesupport/applying_the_segment_pair_confirmation_levels.md +++ b/apiconcepts/filetypesupport/applying_the_segment_pair_confirmation_levels.md @@ -1,33 +1,30 @@ -Applying the Segment Pair Confirmation Levels -=== +# Applying the Segment Pair Confirmation Levels -In this chapter you will learn how to process the BIL unit status information of a given BIL file and apply it to the corresponding segment pair status used by the SDLXliff format. +This section explains how to process BIL unit status information and apply it to the corresponding segment pair status in SDLXLIFF. -Process the Segment Pair Status --- +## Process the Segment Pair Status -Var:ProductName applies various confirmation levels to segment pairs, e.g. draft, translated, approved, etc. Below you see a list of the available confirmation level values that are used in the SDLXliff format: +Var:ProductName applies confirmation levels to segment pairs, such as `draft`, `translated`, and `approved`. The following image shows the confirmation level values that SDLXLIFF uses: ![ConfirmationLevelList](images/ConfirmationLevelList.jpg) -The status attribute of the unit element is the direct equivalent to the segment pair object in Var:ProductName. To keep things simple let us assume that units in a BIL file contain the following status values, which can be mapped to the SDLXliff confirmation levels as outlined below: +The `status` attribute of the `unit` element maps directly to the segment pair status in Var:ProductName. For simplicity, assume that units in a BIL file contain the following status values, which map to SDLXLIFF confirmation levels as shown here: -|BIL | SDLXliff | -| ----------- | ----------- | -| new | unspecified | -| fuzzy | draft | -| exact | translated | +| BIL | SDLXLIFF | +| --- | --- | +| `new` | `unspecified` | +| `fuzzy` | `draft` | +| `exact` | `translated` | -You can apply the appropriate status value to a segment pair object through the [ConfirmationLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISegmentPairProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISegmentPairProperties_ConfirmationLevel) property. First, enhance the ```CreateParagraphUnit()``` helper function by adding the following line, which calls another helper function that maps the confirmation level values. +Apply the correct status value to a segment pair through the [ConfirmationLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISegmentPairProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISegmentPairProperties_ConfirmationLevel) property. First, update the `CreateParagraphUnit()` helper function by adding the following line, which calls another helper function to map the confirmation level values: # [C#](#tab/tabid-1) ```cs segmentPairProperties.ConfirmationLevel = CreateConfirmationLevel(xmlUnit.Attributes["status"].Value); ``` -*** -The complete ```CreateParagraphUnit()``` function should look as shown below: +The complete `CreateParagraphUnit()` function should look like this: # [C#](#tab/tabid-2) ```cs @@ -54,7 +51,6 @@ private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) paragraphUnit.Target.Add(trgSegment); } - #region "context" // create paragraph unit context string id = xmlUnit.SelectSingleNode("./@id").InnerText; if(xmlUnit.SelectSingleNode("type/@spec")!=null) @@ -65,22 +61,17 @@ private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) } else { paragraphUnit.Properties.Contexts = CreateContext("Paragraph", id); } - #endregion - - #region "comments" // extract comment (if applicable) if(xmlUnit.SelectSingleNode("comment")!=null) { paragraphUnit.Properties.Comments = CreateComment(xmlUnit.SelectSingleNode("comment").InnerText); } - #endregion return paragraphUnit; } ``` -*** -Now add the helper function that uses a switch statement to map the BIL status values to the SDLXliff confirmation levels: +Now add the helper function that uses a switch statement to map the BIL status values to SDLXLIFF confirmation levels: # [C#](#tab/tabid-3) ```cs @@ -107,11 +98,11 @@ private ConfirmationLevel CreateConfirmationLevel(string BilStatus) return sdlxliffLevel; } ``` -*** -After making the above additions to the parser class, the SDLXliff document should look in Var:ProductName as shown below. Note that the confirmation levels are visualized through different icons, which are displayed between the source and the target segments. + +After you add this code to the parser class, the SDLXLIFF document in Var:ProductName should look like this. Var:ProductName displays the confirmation levels as icons between the source and target segments. ![ConfirmationLevels](images/ConfirmationLevels.jpg) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/bil_adding_the_file_type_component_builder.md b/apiconcepts/filetypesupport/bil_adding_the_file_type_component_builder.md index 57ab3c80eb..6aa736fdc1 100644 --- a/apiconcepts/filetypesupport/bil_adding_the_file_type_component_builder.md +++ b/apiconcepts/filetypesupport/bil_adding_the_file_type_component_builder.md @@ -1,26 +1,27 @@ -Adding the File Type Component Builder -=== +# Adding the File Type Component Builder -Add the File Type Component Builder to your project. You will need to explicitly implement the interface [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) +Add the File Type Component Builder to your project by explicitly implementing the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) interface. # [C#](#tab/tabid-1) ```cs public class SimpleTextFilterComponentBuilder : IFileTypeComponentBuilder ``` -*** -The component builder contains the complete implementation of the File Type Component Builder. It is used to declare and define the new file type plug-in to the framework, so that it can be used in Var:ProductName. +The component builder contains the complete implementation of the File Type Component Builder. It declares and defines the new file type plug-in to the framework, enabling it to work in Var:ProductName. -Add the File Type Information --- +## Add File Type Information -Your File Type Component Builder needs to contain information such as the file type plug-in version number, the extension of the files that this file type plug-in applies to, etc. This kind of information is shown to users in the **Options** dialog box of Var:ProductName below **File Types**. +Your File Type Component Builder requires information such as the file type plug-in version number and the file extension that the plug-in applies to. Var:ProductName displays this information to users in the **Options** dialog box under **File Types**. -We recommend that you add a resources file to your assembly and call it e.g. **Resources.resx**. Then enter some general information strings such as the file type version, description, etc. into this resources file. These strings (and the embedded assembly icon) are then referenced in the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation. File Type Component Builder. Below is an example of the strings that you should provide in the resources file: +Add a resources file to your assembly and name it **Resources.resx**. Enter general information strings such as the file type version and description into this resources file. Reference these strings (and the embedded assembly icon) in the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation. The following image shows example strings for the resources file: ![BilFilterResources](images/BilFilterResources.jpg) -The [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation contains references to each component of your file type plug-in, e.g. file sniffers, file parsers, etc. If you fail to reference a component in the file type definition, the functionality of the undeclared component cannot be used in Var:ProductName. The File Type Component Builder thereby fully reflects the component structure of the file type plug-in. At this point, we would like to underline the importance of sub-dividing your file type plug-in into distinct components, as each component performs a different, even if sometimes similar, task. The File Type Component Builder file can also contain the values of certain plug-in settings that users can change at runtime. Let us start by adding the general file type information to the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation as shown below: +The [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation references each component of your file type plug-in, such as file sniffers and file parsers. If you fail to reference a component in the file type definition, Var:ProductName cannot use that component's functionality. The File Type Component Builder fully reflects your plug-in's component structure. + +Divide your file type plug-in into distinct components, where each component performs a different task. You can also store runtime-configurable plug-in settings in the File Type Component Builder file. + +The following example shows how to add the general file type information to the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation: # [C#](#tab/tabid-2) ```cs @@ -46,15 +47,12 @@ public IFileTypeInformation BuildFileTypeInformation(string name) return info; } ``` -*** -If you added the File Type Component Builder to Var:ProductName, it would appear in the **Options** dialog box as illustrated below. The file type plug-in will be listed under **File Types**. However, of course it will not have any functionality yet. Below you see an example of how the information entered in the File Type Component Builder is presented to the user through the UI of Var:ProductName: +If you add the File Type Component Builder to Var:ProductName, it appears in the **Options** dialog box under **File Types**. The following image illustrates how Var:ProductName presents the file type information to users: ![OptionsBilFilter](images/OptionsBilFilter.jpg) +The File Type Component Builder is more comprehensive than the example shown above. As you develop each component of your sample file type plug-in, add the corresponding component references to the File Type Component Builder file incrementally. -Of course, a File Type Component Builder file is a lot more comprehensive than what is shown above. As we develop each component of our sample file type plug-in, we will add the corresponding component references to the File Type Component Builder file step by step. - ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/bil_implementing_the_file_sniffer.md b/apiconcepts/filetypesupport/bil_implementing_the_file_sniffer.md index e47924fda4..baefc9b01c 100644 --- a/apiconcepts/filetypesupport/bil_implementing_the_file_sniffer.md +++ b/apiconcepts/filetypesupport/bil_implementing_the_file_sniffer.md @@ -1,21 +1,20 @@ -Implementing the File Sniffer -=== +# Implementing the File Sniffer -In this chapter, we implement the functionality required for determining whether a given BIL file is valid and can be processed by our sample file type plug-in. +Implement the functionality to determine whether a given BIL file is valid and can be processed by your sample file type plug-in. -Identify the File Validation Criteria --- +## Identify File Validation Criteria -For determining whether a given file can be processed by a filter or not, you can, of course, use the file extension, which is also specified in the File Type Component Builder. However, this criterion is not very reliable. Even if the file extension does match, the file might still not be valid for some reason, and can therefore not be processed by the file type plug-in. Moreover, different file types might share the same extension, which is another reason for not relying on file name extensions only. +You can use the file extension (specified in the File Type Component Builder) to determine whether a file can be processed. However, file extensions alone are unreliable. A matching extension doesn't guarantee the file is valid, and different file types may share the same extension. -It is therefore important to determine one more reliable criteria that tell you whether the file is valid or not. The most obvious criterion for an XML file is, of course, the root element, which in this case is ```bilingualdocument```. Let us proceed on the assumption that if a given document has this root element, the file should be considered valid. If not, the file type plug-in should tell the user that the file is not supported. It is recommended that you implement the validation functionality in a distinct file sniffer component. +Implement a more reliable validation criterion. For XML files, the root element provides reliable validation. In this case, the root element is `bilingualdocument`. If a document contains this root element, consider it valid. Otherwise, the file type plug-in should inform the user that the file is not supported. -Add the File Sniffer Class --- +Implement the validation functionality in a distinct file sniffer component. -Add a new class called e.g. **BilSniffer.cs** to your project. This class needs to implement the [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml) interface. Note that even though we are developing a bilingual file type plug-in (and not a native file type plug-in), we require the above-mentioned interface. The sniffer component determines the validity of the file based on file-specific (native) criteria (in our example the root element). +## Add the File Sniffer Class -The interface implements a [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method, which returns a [SniffInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml) object. Through this object you can, for example, set whether a given file is supported or not. The minimum amount of code required to build a file sniffer component looks as shown below: +Create a new class called **BilSniffer.cs** and implement the [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml) interface. Although you're developing a bilingual file type plug-in (not a native file type plug-in), you must use this interface. The sniffer component determines file validity based on file-specific (native) criteria, such as the root element in this example. + +The interface implements a [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method that returns a [SniffInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml) object. You can use this object to set whether a file is supported or not. The following shows the minimum code required for a file sniffer component: # [C#](#tab/tabid-1) ```cs @@ -42,20 +41,42 @@ namespace Sdk.Snippets.Bilingual } } ``` -*** +# [C#](#tab/tabid-1) +```cs +using Sdl.Core.Settings; +using Sdl.FileTypeSupport.Framework.NativeApi; +using Sdl.Core.Globalization; -Implement the Sniffer Logic --- +namespace Sdk.Snippets.Bilingual +{ + class BilSniffer : INativeFileSniffer + { + public SniffInfo Sniff( + string nativeFilePath, + Language language, + Codepage suggestedCodepage, + INativeTextLocationMessageReporter messageReporter, + ISettingsGroup settingsGroup) + { + SniffInfo fileInfo = new SniffInfo(); + return fileInfo; + } + } +} +``` + +## Implement the Sniffer Logic -Now you implement the actual logic required to determine whether a given file is supported or not. Remember, that if you have specific settings which need to be applied to the file sniffer, these can be populated using the ```ISettingsGroup``` which is passed in via the Sniff method. Please see [The File Sniffer](the_file_sniffer.md) for more details. The file sniffer reads the root element name from a given document. In our sample format, the root element also contains the source and target language information, e.g.: +Implement the logic to determine whether a given file is supported. If you have specific settings for the file sniffer, populate them using the `ISettingsGroup` passed to the Sniff method. See [The File Sniffer](the_file_sniffer.md) for more details. + +The file sniffer reads the root element name from the document. In this sample format, the root element also contains the source and target language attributes: # [Xml](#tab/tabid-2) ```xml ``` -**** -As we are going to retrieve these three items from the root element, it makes sense to add the root element name to search for as well as the source/target language attribute names as constants to our sniffer class: +Add the root element name, source language attribute name, and target language attribute name as constants to your sniffer class: # [C#](#tab/tabid-3) ```cs @@ -63,9 +84,8 @@ static string _BilingualDocument = "bilingualdocument"; static string _SourceLanguage = "source-language"; static string _TargetLanguage = "target-language"; ``` -**** -The [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method then calls two separate helper functions to read the root element name and the source/target language values. Depending on the result returned by the ```IsFileSupported()``` helper function, the [IsSupported](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_IsSupported) property is set to True or to False: +The [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method calls two helper functions to read the root element name and source/target language values. The [IsSupported](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_IsSupported) property is set to True or False based on the result from the `IsFileSupported()` helper function: # [C#](#tab/tabid-4) ```cs @@ -90,14 +110,11 @@ public SniffInfo Sniff(string nativeFilePath, Language suggestedSourceLanguage, return info; } ``` -*** -The ```IsFileSupported()``` helper function receives the file name and path from the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method. It then loads the document into an XML DOM object to determine the root element, and returns True or False. +The `IsFileSupported()` helper function receives the file name and path. It loads the document into an XML DOM object to determine the root element and returns True or False: # [C#](#tab/tabid-5) ```cs -// determine whether a given file is supported based on the -// root element private bool IsFileSupported(string nativeFilePath) { bool result = false; @@ -111,14 +128,13 @@ private bool IsFileSupported(string nativeFilePath) return result; } ``` -*** -The ``GetFileLanguages()`` helper function retrieves the file info object as well as the file name and path from the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method. It then loads the document into an XML DOM object to read the source and target language attribute values. After that, it sets the properties for the detected source and target languages to the values that were retrieved from the root element attributes. In our example the root element attributes clearly state the source and target language. This is why we can set the [DetectionLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml) property to [Certain](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields). For document types in which the languages have to be determined, for example, based on heuristics, you may want to set the detection level to one of the other possible values, e.g. [Likely](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields) or [Guess](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields). +The `GetFileLanguages()` helper function retrieves the file info object, file name, and path. It loads the document into an XML DOM object to read the source and target language attribute values. It then sets the detected source and target language properties with the values retrieved from the root element attributes. + +In this example, the root element attributes clearly state the source and target language, so set the [DetectionLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml) property to [Certain](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields). For document types where languages must be determined using heuristics, set the detection level to [Likely](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields) or [Guess](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields): # [C#](#tab/tabid-6) ```cs -// retrieve the source and target language -// from the file header private void GetFileLanguages(ref SniffInfo info, string nativeFilePath) { XmlDocument doc = new XmlDocument(); @@ -143,24 +159,21 @@ private void GetFileLanguages(ref SniffInfo info, string nativeFilePath) } } ``` -*** -If the detection level is set to [Certain](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields), the language dropdown lists in the **Open Document** dialog box will be disabled, and thus cannot be changed by the user. Otherwise, end users can change the proposed language combination at their discretion. +When the detection level is set to [Certain](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.DetectionLevel.yml#fields), the language dropdown lists in the **Open Document** dialog are disabled and cannot be changed by the user. Otherwise, users can change the proposed language combination as needed. ![LanguagesAutoDeteced](images/LanguagesAutoDeteced.jpg) -When the language pair has been programmatically determined by the sniffer, the user does not have to select the source/target language combination manually upon opening the file. The language pair will be displayed in the status bar of Var:ProductName, e.g.: +When the sniffer programmatically determines the language pair, users don't need to manually select the source/target language combination when opening the file. Var:ProductName displays the language pair in the status bar: ![LanguagePair](images/LanguagePair.jpg) ->[!NOTE] -> ->If the sniffer determines that the file is not supported, you should communicate this to the user. This is done in the same way as in a native file type plug-in. See chapter [User Communication Through Messaging](user_communication_through_messaging.md) for more information and for an example on how to provide users with information on why a given file cannot be processed. +> [!NOTE] +> If the sniffer determines that the file is not supported, inform the user. See [User Communication Through Messaging](user_communication_through_messaging.md) for information on how to provide users with details about why a file cannot be processed. -Add the Component Reference to the Component Builder --- +## Add the Component Reference to the Component Builder -Do not forget to reference the file sniffer component to the File Type Component Builder by inserting the following code to your implementation of the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) interface. Remember that failure to do so will mean that this component will never be used by the file type plug-in, even if the sniffer has been implemented in the assembly. +Reference the file sniffer component in the File Type Component Builder by adding the following code to your [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation. If you fail to reference this component, it will not be used by the file type plug-in, even if the sniffer is implemented in the assembly. # [C#](#tab/tabid-7) ```cs @@ -169,12 +182,10 @@ public INativeFileSniffer BuildFileSniffer(string name) return new BilSniffer(); } ``` -*** -Putting it All Together --- +## Putting It All Together -The complete sniffer class should now look as shown below: +The complete sniffer class should look as follows: # [C#](#tab/tabid-8) ```cs @@ -191,13 +202,10 @@ namespace Sdk.FileTypeSupport.Samples.Bil { class BilSniffer : INativeFileSniffer { - #region "constants" static string _BilingualDocument = "bilingualdocument"; static string _SourceLanguage = "source-language"; static string _TargetLanguage = "target-language"; - #endregion - #region "sniff" public SniffInfo Sniff(string nativeFilePath, Language suggestedSourceLanguage, Codepage suggestedCodepage, INativeTextLocationMessageReporter messageReporter, ISettingsGroup settingsGroup) @@ -218,11 +226,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil return info; } - #endregion - #region "issupported" - // determine whether a given file is supported based on the - // root element private bool IsFileSupported(string nativeFilePath) { bool result = false; @@ -235,11 +239,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil return result; } - #endregion - #region "get languages" - // retrieve the source and target language - // from the file header private void GetFileLanguages(ref SniffInfo info, string nativeFilePath) { XmlDocument doc = new XmlDocument(); @@ -263,18 +263,13 @@ namespace Sdk.FileTypeSupport.Samples.Bil } } } - #endregion } } ``` -*** -See Also --- - +## See Also -[User Communication Through Messaging](user_communication_through_messaging.md) +- [User Communication Through Messaging](user_communication_through_messaging.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/bilingual_file_parser.md b/apiconcepts/filetypesupport/bilingual_file_parser.md index 1344bef71c..414710c1e5 100644 --- a/apiconcepts/filetypesupport/bilingual_file_parser.md +++ b/apiconcepts/filetypesupport/bilingual_file_parser.md @@ -1,106 +1,99 @@ -The Bilingual File Parser -=== +# The Bilingual File Parser -The bilingual parser is used for localizable content extraction. While the native parser allows you to extract source related localizable content, the bilingual parser allows you to set source and target related localizable content, group this content into the paragraph units and the segments. +The bilingual parser extracts localizable content from bilingual documents. Unlike a native parser, which extracts source content only, a bilingual parser can set both source and target content and group that content into paragraph units and segments. -Writing a bilingual parser --- +## Writing a bilingual parser -When writing filters to use the Bilingual API you must first derive your parser class from the [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) and [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interfaces. These two interfaces form the core of the work that is done by a Bilingual parser. +When you build a filter with the Bilingual API, the parser must implement [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml). In practice, the parser also participates in the bilingual content-processing pipeline through [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml). -Some other interaces may be also required such as [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) or [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). +You may also need to implement additional types, such as [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) and [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml). -However, the simplest way to implement a Bilingual parser is to derive from the [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) class and the [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) and [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface only and use the helper functions and properties of the [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) class. A parser normally derives from the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface which provides the parser with additional information such as the original file path name, source and target language and encoding and class methods that are called during key phases of the parsing process to enable your filter to manage its initialisation flow-control and clean-up. You should also derive from the [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) interface if you have any settings associated with this parser. Of course, you will need to create a UI to set the settings as well. Please see [Filter UI Settings](filter_ui_settings.md) for more information. +The simplest approach is to derive from [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) and implement [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) and [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). This base class provides helper properties and methods that reduce the amount of code you need to write. -Deriving from AbstractBilingualFileTypeComponent --- +`INativeContentCycleAware` gives the parser access to information such as the original file path, source and target languages, and encoding. It also provides methods that the framework calls at key stages of parsing so that your filter can initialize and clean up correctly. If the parser uses settings, implement [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) and provide a UI for those settings. For more information, see [Filter UI Settings](filter_ui_settings.md). -The [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) base class provides an implementation of the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) and [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml) interfaces leaving only the [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) and [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interfaces to be implemented by the derived class. If this class is used as a base class then most of the properties and methods that a required to implement a Bilingual parser will be implemented in this [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) class or its base class. This leaves the following interfaces that still need to have their interface members implemented in your bilingual parser class: [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml), IParser and [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). +## Using `AbstractBilingualFileTypeComponent` -Implementing IBilingualParser --- +The [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) base class already implements [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) and [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml). This leaves your parser to implement the members required by [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml), `IParser`, and [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). -The [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) interface contains two essential properties for the bilingual parser. +## Implementing `IBilingualParser` -The first property ```DocumentProperties``` contains an [IDocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml) interface that is set by the Bilingual API during the parser initialisation. This document properties interface is used to initialise the source and target languages. +The [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) interface defines two essential properties. -The second property [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) of type [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) is used to tell the Bilingual API of all major file processing events that are encountered during the parsing of a bilingual document. The [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface is implemented by content processors within the Bilingual API that work on the bilingual content model. To facilitate processing in a streaming manner without requiring the entire document object in memory at any time the parser will need to feed paragraph-units one by one through calls to ```Output.ProcessParagraphUnit()```. However, document and file properties will need to be provided by the parser to the framework by calls to ```Output.Initialize()``` and ```Output.SetFileProperties()``` before processing any paragraph-units in each document or file. These events are outlined in the next few sections below. +### `IBilingualParser.DocumentProperties` -**IBilingualParser.DocumentProperties** +The [DocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualParser_DocumentProperties) property holds an [IDocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml) instance. The Bilingual API sets this property during parser initialization. You store the value and then use it to set the source and target languages and initialize the output stream. -The [DocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualParser_DocumentProperties) interface of type [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) is set by the File Type Support Framework when calling a bilingual parser but you will need to define this property and a private member to store its value. This document properties interface is then later used for storing the source and target languages and then initialising the output stream of the bilingual content processes. +### `IBilingualContentProcessor.Output` -**IBilingualContentProcessor.Output** +The [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) property is of type [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml). The framework initializes it and uses it to connect the bilingual parser to the content processors further down the processing chain during extraction from a bilingual file format to the default bilingual SDLXLIFF (`*.xliff`) persistent format. -The [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) interface of type [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) is also initialised by the File Type Support Framework and provides a coupling between the Bilingual Parser and all Bilingual Content Processors down the processing chain during the extract conversion phase from a bilingual file format to the default bilingual SDLXliff (*.xliff*) persistent file format. The [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) interface has several methods that are called throughout the file parsing operation. +To support streaming and avoid loading the entire document into memory, the parser should feed paragraph units one at a time through `Output.ProcessParagraphUnit()`. Before it processes any paragraph units, it must also provide document and file properties through `Output.Initialize()` and `Output.SetFileProperties()`. -**Output.Initialize()** +### `Output.Initialize()` -The Bilingual Parser should call [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) method to forward the reference to the [DocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualParser_DocumentProperties) object for the document being processed. This is normally done after the [SourceLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_SourceLanguage) and [TargetLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_TargetLanguage) have been set using information from the source file being parsed. +Call [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) to pass the [DocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualParser_DocumentProperties) object for the current document. Do this after you set [SourceLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_SourceLanguage) and [TargetLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_TargetLanguage) from the source file. >[!NOTE] > ->This method should always be called, and always before any other calls on the [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) interface. +> This method should always be called before any other call on the [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) interface. -**Output.SetFileProperties()** +### `Output.SetFileProperties()` -The Bilingual Parser should call [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) method to provide the framework with a reference to the properties for each file in the document, before the paragraph-units of the file are processed by calling [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) as outlined below. +Call [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) to provide the framework with the properties for each file in the document. Call it before you process the file's paragraph units through [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_). -The [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) method takes an interface reference of type [IFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IFileProperties.yml) that needs to be created by the Bilingual Parser its self. This can be done using the [CreateFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentItemFactory.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentItemFactory_CreateFileProperties) method. However, a Bilingual parser will normally need to set the [IPersistentFileConversionProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml) property of the [IFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IFileProperties.yml) created object before passing it to [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_). This property however can normally be obtained from the parameter of [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) when your parser class is derived from [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). You may also need to update other properties of the [IFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IFileProperties.yml) object such as source and target language Tool name and version and creation date. +`SetFileProperties()` takes an [IFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IFileProperties.yml) instance. The bilingual parser must create this instance, typically by using [CreateFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentItemFactory.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentItemFactory_CreateFileProperties). In most cases, the parser should also set the [IPersistentFileConversionProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml) property before it passes the object to `SetFileProperties()`. When your parser implements [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml), you can usually obtain this information from the file properties that the framework passes into the content cycle. You may also need to set other values on [IFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IFileProperties.yml), such as the source language, target language, tool name, tool version, and creation date. -**Output.ProcessParagraphUnit()** +### `Output.ProcessParagraphUnit()` -The Bilingual Parser should call [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) method for each paragraph-unit found in the source file being parsed. The parameter of type [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) must be created using a call to [CreateParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentItemFactory.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentItemFactory_CreateParagraphUnit_Sdl_FileTypeSupport_Framework_NativeApi_LockTypeFlags_). When creating a paragraph-unit the source and target language is specified together with a lock type. Normally paragraph-units are created as structure paragraph-units with lock type [Structure](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml#fields) or translatable paragraph-unit of lock type [Unlocked](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml#fields). +Call [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) for each paragraph unit in the source file. Create the [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) instance by calling [CreateParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentItemFactory.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentItemFactory_CreateParagraphUnit_Sdl_FileTypeSupport_Framework_NativeApi_LockTypeFlags_). When you create a paragraph unit, specify the source language, target language, and lock type. In most cases, paragraph units are either structure paragraph units with the [Structure](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml#fields) lock type or translatable paragraph units with the [Unlocked](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml#fields) lock type. -**Output.FileComplete()** +### `Output.FileComplete()` -The Bilingual Processor should call [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) method after all paragraph-units in a file have been processed by calling [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) for each one. After calling [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) the file properties should not be changed any further. +Call [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) after you process all paragraph units in a file. After you call `FileComplete()`, do not change the file properties. -**Output.Complete()** +### `Output.Complete()` -The Bilingual Processor should call [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) method after all content in all files have been processed. After calling [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) the document properties should not be changed any further. +Call [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) after you process all content in all files. After you call `Complete()`, do not change the document properties. -Implementing IParser --- +## Implementing `IParser` -**IParser.OnProgress** +### `IParser.OnProgress` -The [IParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IParser.yml) interface contains an event [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) or type [ProgressEventArgs](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ProgressEventArgs.yml) that must be defined in classes deriving from it. This event can be used to notify the framework and hence the user of the file parsing progress. As well as calling [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) with a suitable percentage of the file currently being processed it is normally expected to be called with a parameter of 0% before opening a file and with a parameter of 100% when file reading is complete. +The [IParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IParser.yml) interface defines an [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) event of type [ProgressEventArgs](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ProgressEventArgs.yml). Use this event to notify the framework, and therefore the user, about parsing progress. In most cases, you should raise it with `0` before you open a file, update it with the current percentage during parsing, and raise it with `100` when parsing is complete. -**IParser.ParseNext()** +### `IParser.ParseNext()` -The [IParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IParser.yml) interface contains a [ParseNext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_IParser_ParseNext) method which must also be implemented. This method is called repeatedly by the framework to process the next chunk of input from the source bilingual document. +The [IParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IParser.yml) interface also requires the [ParseNext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_IParser_ParseNext) method. The framework calls this method repeatedly to process the next chunk of input from the source bilingual document. -The implementation should parse a suitable chunk (preferably not large) of the input and return a bool that indicates if there is more work to be done before this file is completely parsed. When there is no more of the source file to process then the [ParseNext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_IParser_ParseNext) method should return false to indicate that there is no more file content to be processed. +The implementation should parse a suitable chunk of input, preferably a small one, and return a Boolean value that indicates whether more work remains. Return `false` when the parser has processed all file content. -Typically it is in this method, or in methods called by this, that the Output property’s methods are called to inform the framework of the entire source files content. +Typically, this method, or methods that it calls, invoke the `Output` property methods to report the source file content to the framework. -Implementing INativeContentCycleAware --- +## Implementing `INativeContentCycleAware` -If deriving from the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface you must implement the following three methods. +If your parser implements [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml), it must implement the following three methods. -**SetFileProperties()** +### `SetFileProperties()` -[SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) methods standard implementation is to save its parameter properties of type [IFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IFileProperties.yml) to a class variable. These file properties can then be used by the bilingual parser to supplement the information available from the source file contents where this information may not be known, such as the original file encoding. +The standard implementation of [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) stores its [IFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IFileProperties.yml) parameter in a class field. The bilingual parser can then use these file properties to supplement information from the source file, such as the original encoding. -**StartOfInput()** +### `StartOfInput()` -Called by the framework after component initialisation i.e. after [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) , but before any content is parsed and passed to any of the File Type Support Framework components. +The framework calls this method after component initialization, including [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_), but before it parses and passes any content to File Type Support Framework components. -**EndOfInput()** +### `EndOfInput()` -This is called by the framework after processing of the bilingual content has finished. +The framework calls this method after it finishes processing the bilingual content. -Implementing ISettingsAware --- +## Implementing `ISettingsAware` -If deriving from the [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) interface you must implement the following method. +If your parser implements [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml), it must implement the following method. -**InitializeSettings()** +### `InitializeSettings()` -[InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) Passes in an [ISettingsBundle](../../api/core/Sdl.Core.Settings.ISettingsBundle.yml) object and a ```configurationId``` ```FileTypeConfigurationId```. These can be used to populate the required settings object used by the parser: +[InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) passes an [ISettingsBundle](../../api/core/Sdl.Core.Settings.ISettingsBundle.yml) object and a `configurationId` (`FileTypeConfigurationId`). Use these values to populate the settings object that the parser requires: # [C#](#tab/tabid-1) ```cs @@ -113,12 +106,9 @@ public void InitializeSettings(Sdl.Core.Settings.ISettingsBundle settingsBundle, ``` *** -See Also --- +## See also - - -[The File Parser](the_file_parser.md) +- [The File Parser](the_file_parser.md) >[!NOTE] diff --git a/apiconcepts/filetypesupport/bilingual_file_sniffer.md b/apiconcepts/filetypesupport/bilingual_file_sniffer.md index eafb9d7d50..3c28ca5d21 100644 --- a/apiconcepts/filetypesupport/bilingual_file_sniffer.md +++ b/apiconcepts/filetypesupport/bilingual_file_sniffer.md @@ -1,15 +1,11 @@ -The File Sniffer -=== +# The File Sniffer -The file sniffer for bilingual filters is using the same features as for native filters. See [The File Sniffer](the_file_sniffer.md) for more details. +The file sniffer for bilingual filters uses the same features as the file sniffer for native filters. For more information, see [The File Sniffer](the_file_sniffer.md). -See Also --- +## See Also - - -[The File Sniffer](the_file_sniffer.md) +- [The File Sniffer](the_file_sniffer.md) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out of date. To verify the latest information on this topic, inspect the libraries in the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/bilingual_file_type_plugin_introduction.md b/apiconcepts/filetypesupport/bilingual_file_type_plugin_introduction.md index a9de6e43ff..295cc11ae7 100644 --- a/apiconcepts/filetypesupport/bilingual_file_type_plugin_introduction.md +++ b/apiconcepts/filetypesupport/bilingual_file_type_plugin_introduction.md @@ -1,20 +1,25 @@ -Introduction -=== +# Bilingual File Type Plug-in Overview -While the first version of the File Type Support Framework, which was used in SDL Trados 2007, could only process native, monolingual files, the new version also supports bilingual documents such as TTX, ITD, and XLIFF. +The File Type Support Framework processes bilingual documents containing both source and target language content. Var:ProductName supports Bilingual Excel, Bilingual Word Documents, and XLIFF 2.0 formats. -About Bilingual File Type Plug-in --- -The processing of bilingual formats follows the same basic concept as the processing of monolingual (native) formats: the bilingual format is opened in Var:ProductName, and then converted to an intermediary format (e.g. SDLXliff). The intermediary document that is derived from the bilingual format is then further processed, e.g. it is translated, analyzed, etc. Afterwards, the intermediary file is converted back into the original bilingual format. +## How Bilingual File Type Plug-ins Work -As the name suggests, bilingual files contain strings in more than one language. They usually have source-language segments and (possibly) segments in the target language. Bilingual files can thus be partly pre-translated documents. +Bilingual file processing follows the same concept as monolingual (native) file processing: -Probably the most common example of this is the processing of TTX (TradosTag) and ITD files in Var:ProductName. TTX and ITD are the predecessor formats of SDLXliff, which are used in SDL Trados 2007 and SDLX 2007. For compatibility reasons, these formats are still supported in Var:ProductName. This allows users of Var:ProductName to e.g. open a partly-translated TTX file, finish translating it, and generate the fully translated TTX file, which can then be further processed in an SDL Trados 2007-based workflow. +1. Var:ProductName opens the bilingual file and converts it to an intermediary format (SDLXliff). +2. The system processes the intermediary document through translation, analysis, or review. +3. The intermediary file converts back to the original bilingual format. -![TTXandITD](images/TTXandITD.jpg) +Bilingual files store strings in multiple languages. Each source-language segment pairs with a corresponding target-language segment. These files often arrive partly pre-translated. -The TTX and ITD file types as examples of bilingual file type plug-ins. +## Supported Bilingual Formats ->[!NOTE] -> -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +Var:ProductName supports the following bilingual file formats: + +* **Bilingual Excel (*.xlsx)**: Organizes source and target segments in designated columns side-by-side. This format suits spreadsheet-based translation workflows. + +* **Bilingual Word Document (*.doc, *.docx)**: Presents source and target text in a word processing environment familiar to translators. + +* **XLIFF 2.0 (*.xlf, *.xliff)**: Provides an industry-standard XML-based format for exchanging localizable data between tools. XLIFF 2.0 delivers robust support for translation metadata, inline markup, and segmentation. + +Users open partly-translated files in Var:ProductName, complete the translation, and generate fully translated output for downstream workflows. diff --git a/apiconcepts/filetypesupport/bilingual_file_writer.md b/apiconcepts/filetypesupport/bilingual_file_writer.md index 8119bd1bf1..3460c2779d 100644 --- a/apiconcepts/filetypesupport/bilingual_file_writer.md +++ b/apiconcepts/filetypesupport/bilingual_file_writer.md @@ -1,52 +1,48 @@ -The Bilingual File Writer -=== +# The Bilingual File Writer -The bilingual file writer component is responsible for translated file creating. While the native file writer has access only to the target content, the bilingual filter has access to each paragraph-unit object and can access both source and target segments as well as other bilingual model objects like context etc. +The bilingual file writer component creates translated files. Unlike the native file writer, which accesses only target content, the bilingual writer accesses each paragraph-unit object and can retrieve both source and target segments, as well as other bilingual model objects such as context. -Writing a bilingual writer --- +## Writing a bilingual writer -When writing a bilingual file writer you must derive your writer class from the interfaces [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml) and [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml). These interfaces provide a way of coupling to the File Type Support Framework and allowing it to initialise the writer with the necessary objects it needs to interact with the framework. A writer will also normally derive from the INativeOutputSettingsAware and [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) interfaces which provide the writer with additional information such as the target file path name and preferred target encoding and allow for the population of any associated writer settings objects. +Derive your writer class from the [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml) and [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interfaces. These interfaces couple your writer to the File Type Support Framework and enable it to initialize with the necessary objects for framework interaction. Writers typically also derive from `INativeOutputSettingsAware` and [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml), which provide target file path, target encoding, and writer settings information. -However, the simplest way to implement a Bilingual Writer is to derive from the [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml) class rather than directly from the [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface. +For simplicity, derive from the [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml) class instead of directly implementing [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml). -When processing files in a Bilingual Processor the Framework API has the facility to separate compound or multiple documents into individual files for processing. This facility forms part of the [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface and a group of documents is initialised during the [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) call and finalised during the [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) call. Between these calls multiple sub-documents or files are initialised by a call to [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) and flagged as complete during call to [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete). For each individual file within a compound or multiple file document the file processing is broken into manageable units of translatable content or paragraph-units and each of these [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) based objects is processed in the [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) call. +The Framework API separates compound or multiple documents into individual files for processing as part of the [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface. The framework initializes document groups during the [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) call and finalizes them during the [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) call. Between these calls, the framework initializes multiple sub-documents or files by calling [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) and marks them complete by calling [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete). For each file, the framework breaks processing into manageable units of translatable content (paragraph-units). Each [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) object is processed through the [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) call. -Deriving from AbstractBilingualFileTypeComponent --- +## Deriving from AbstractBilingualFileTypeComponent -The [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) base class provides an implementation of the [IBilingualContentMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml) and [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml) interfaces leaving the [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) and [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml) interfaces to be implemented by the derived class. If the [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) class is used as a base class then this saves the derived class from having to provide implementations for the properties of the base interfaces that it is derived from. This also enables the use of the helper function [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_) by its derived classes. +The [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) base class implements [IBilingualContentMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml) and [IBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualFileTypeComponent.yml), leaving [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) and [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml) for your derived class to implement. Using this base class eliminates the need to implement inherited interface properties and methods, and grants access to the [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_) helper function. -You may have noticed that the [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface that the Bilingual Writer is derived from is the same interface that is used for the [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) property of the [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) based Bilingual Parser. This is so that all text, tags and other mark-up items that are written during the parsing phase are re-used for the translated file writing phase with the mark-up order and translated text content determined by the translation process, However, the translated document will only contain tags that were created during the parsing phase and the Bilingual Writer can rely on the tag content of each tag to be the same as it was when it was written by the parser with the exception of any manually mark-up in a framework based editor. If a filter does allow for manually created mark-up such as added **Bold**, *Italic* or Underlined formatting in the translation then this will be defined in the File Type Component Builder file. The only other exception to this is when the parser class has created a tag with localizable content in it. If this is the case then the LocalizableContent property of the tag properties must be examined to retrieve the text for the localizable sub-segments. +The [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface used by the Bilingual Writer is the same interface used by the [Output](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentProcessor_Output) property of the [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) based Bilingual Parser. This design reuses text, tags, and markup items written during parsing for the translated file writing phase, with markup order and content determined by the translation process. The translated document contains only tags created during parsing, and the Bilingual Writer can rely on tag content to remain identical to what the parser wrote, except for manually added markup in framework-based editors. If your filter allows manually created markup such as **Bold**, *Italic*, or Underlined formatting in translations, this must be defined in the File Type Component Builder file. Another exception occurs when the parser creates a tag with localizable content. In this case, examine the tag properties' `LocalizableContent` property to retrieve text for localizable sub-segments. -The coding of the writer class is usually simpler than the parser as the actual tag content can usually be used verbatim when writing file types such as XML and HTML (provided they were extracted as the actual XML or HTML tag content). For other file types the tag content should refer to the type or location of the formatting or mark-up that the tag represents. This tag content string referring to formatting or mark-up in the original document is normally written as a custom XML tag. If required the original document can be encoded during the parsing phase and a copy made available to the Bilingual API writer, please see [DependencyFiles](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_DependencyFiles) property for more details on how to include dependency files during the parsing phase. +Writer class code is typically simpler than parser code. For XML and HTML file types, you can usually use tag content verbatim (if extracted as actual XML or HTML tag content). For other file types, tag content should reference the type or location of the formatting or markup that the tag represents, typically written as a custom XML tag. If needed, encode the original document during the parsing phase and make a copy available to the Bilingual API writer. See [DependencyFiles](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_DependencyFiles) for details on including dependency files during the parsing phase. -Implementing IBilingualContentProcessor --- +## Implementing IBilingualContentProcessor -The Bilingual Writer class will need to derive from [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) and provide implementations of its inherited abstract properties and methods. These properties and methods provide a way of coupling the Bilingual Writer class to the File Type Support Framework in a way that mirrors the same API methods and properties that were used during the parsing phase. It is also worth noting that the same [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface is used for Bilingual Content Processors that are able to be included in the chain of processing during the extract or generate phase to modify or enhance the content generated by a filter or editor. +Derive your Bilingual Writer class from [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) and implement its abstract properties and methods. These properties and methods couple your writer to the File Type Support Framework, mirroring the API methods and properties used during parsing. The same [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface is used for Bilingual Content Processors that participate in the extraction or generation processing chain to modify or enhance filter or editor content. -To facilitate processing in a streaming manner without requiring the entire document object in memory at any time the implementation of a [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface will be fed paragraph-units one by one through calls to [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_). Document and file properties will also be provided by the framework by calling [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) and setting [IDocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml) before processing paragraph-units in each document or file. +Your [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) implementation processes streaming data efficiently without keeping the entire document in memory. The framework feeds paragraph-units one at a time through [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) calls. The framework provides document and file properties by calling [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) and setting [IDocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml) before processing paragraph-units in each document or file. -**Initialize()** +### Initialize() -The framework will call [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) method to provide the implementation with a reference to the document properties for the document being processed. Most implementations of this interface will simply store the parameter of type [IDocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml) in a private member variable. This method will always be called, and always before any other calls on this interface. This or other content processor implementations may modify the document properties as part of the document processing. If you need to access the final version of the document properties you should do that in the [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) method implementation. +The framework calls [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) to pass a reference to the document properties for the document being processed. Most implementations store the [IDocumentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentProperties.yml) parameter in a private member variable. This method is always called first, before any other calls on this interface. Content processor implementations may modify document properties during processing. Access the final document properties in the [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) method implementation. -**Complete()** +### Complete() -[Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) method is called by the framework when all content has been processed. It is now pretty safe to assume that document properties will not change any further. Any class tidy-up can be done here as apposed to within the [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) method below that is normally used for individual file processing tidy-up. +The framework calls [Complete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_Complete) after all content has been processed. Document properties are now finalized and will not change further. Perform class-level cleanup here, in contrast to the [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) method, which handles individual file cleanup. -**SetFileProperties()** +### SetFileProperties() -The framework will call [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) method to provide the implementation with a reference to the properties for each file in the document, before the individual paragraph-units of the file are processed. This Bilingual Writer or other content processor implementations may modify the properties as part of the file processing. If you need to access the Final version of the file properties you should do that in the [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) method implementation. +The framework calls [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) to pass a reference to the properties for each file in the document, before the individual paragraph-units are processed. Your Bilingual Writer or other content processor implementations may modify properties during file processing. Access the final file properties in the [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) method implementation. -**FileComplete()** +### FileComplete() -[FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) method is called by the framework after all paragraph-units in a file have been processed by all components. It is now pretty safe to assume that file properties won't change further. Individual file processing tidy-up can also be done in the implementation of this method. +The framework calls [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_FileComplete) after all paragraph-units in a file have been processed by all components. File properties are now finalized and will not change further. Perform individual file cleanup in this method implementation. -**ProcessParagraphUnit()** +### ProcessParagraphUnit() -The framework will call [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) method for each paragraph-unit in each individual file that is processed. It is up to the implementer of the Bilingual filter how the passed [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) object is processed but there is an implementation of the visitor pattern that can be used with these paragraph-unit objects. +The framework calls [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) for each paragraph-unit in each individual file. Your implementation determines how to process the passed [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) object. The visitor pattern can be used with paragraph-unit objects to simplify processing. # [C#](#tab/tabid-1) ```cs @@ -59,14 +55,10 @@ public void InitializeSettings(Sdl.Core.Settings.ISettingsBundle settingsBundle, ``` *** -See Also --- +## See Also - - -[The File Writer](the_file_writer.md) - -[IMarkupDataVisitor](imarkupdatavisitor.md) +- [The File Writer](the_file_writer.md) +- [IMarkupDataVisitor](imarkupdatavisitor.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/bilingual_filter_ui_settings.md b/apiconcepts/filetypesupport/bilingual_filter_ui_settings.md index 494cf5e858..1747326219 100644 --- a/apiconcepts/filetypesupport/bilingual_filter_ui_settings.md +++ b/apiconcepts/filetypesupport/bilingual_filter_ui_settings.md @@ -1,14 +1,10 @@ -Filter UI Settings -=== +# Filter UI Settings -The filter UI settings for the bilingual filter is using the same set of features as for the native filter, there are no differences in the functionality or the impact on the user interface. +The bilingual filter's UI settings use the same features as the native filter. The functionality and user interface impact are identical. -See Also --- +## See Also - - -[Filter UI Settings](filter_ui_settings.md) +- [Filter UI Settings](filter_ui_settings.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/build_the_file_type_plug_in.md b/apiconcepts/filetypesupport/build_the_file_type_plug_in.md index d2ab085d6d..2c78655331 100644 --- a/apiconcepts/filetypesupport/build_the_file_type_plug_in.md +++ b/apiconcepts/filetypesupport/build_the_file_type_plug_in.md @@ -1,54 +1,48 @@ -Build the File Type Plug-in -=== +# Build the file type plug-in -This chapter contains important information on building your file type plug-in and on the plug-in package file, which is created during the building process. +This article explains how to build a file type plug-in and how Var:ProductName packages it. -The Plug-in Package --- +## The plug-in package -Building the project will generate a **.sdlplugin* file, in our example Sdl.Sdk.FileTypeSupport.Samples.SimpleText.sdlplugin, which will be placed inside your build output path. The **.sdlplugin* file is technically speaking a ZIP archive that contains the required plug-in components such as the plug-in binary (*.dll itself), the resources file, the manifest etc. For our example, the **.sdlplugin* file will contain the following: +When you build the project, Visual Studio generates an `.sdlplugin` file. In this example, the output file is `Sdl.Sdk.FileTypeSupport.Samples.SimpleText.sdlplugin`. The build places that file in your output folder. -* The plug-in assembly, e.g. **Sdl.Sdk.FileTypeSupport.Samples.SimpleText.dll** -* The plug-in manifest, e.g. **Sdl.Sdk.FileTypeSupport.Samples.SimpleText.plugin.xml**. The manifest lists information on any extension classes that the plug-in contains. It is this manifest that will be created during the build process. It declares the assembly and the corresponding extension classes to Var:ProductName. By deleting this manifest **.xml* file you would actually deactivate the plug-in and 'hide' it from the application. -* The plug-in resources file, e.g. **Sdl.Sdk.FileTypeSupport.Samples.SimpleText.plugin.resources**. This resources file contains all the localizable strings and images referred to within the plug-in manifest, and is compiled from **PluginResources.resx** (see also The [Resources File](the_resources_file.md)). +An `.sdlplugin` file is a ZIP archive that contains the plug-in components, such as the plug-in assembly, resources file, and manifest. In this example, the package contains the following files: -The Plug-in Package Path --- -In order for Var:ProductName to pick up the plug-in package and to extract it, the following folders need to be available on your hard drive: +- The plug-in assembly, for example `Sdl.Sdk.FileTypeSupport.Samples.SimpleText.dll`. +- The plug-in manifest, for example `Sdl.Sdk.FileTypeSupport.Samples.SimpleText.plugin.xml`. The build process generates this manifest. It lists the extension classes in the plug-in and declares the assembly and extension classes to Var:ProductName. If you delete this `.xml` file, Var:ProductName no longer loads the plug-in. +- The plug-in resources file, for example `Sdl.Sdk.FileTypeSupport.Samples.SimpleText.plugin.resources`. This file contains the localizable strings and images referenced in the plug-in manifest. The build compiles it from `PluginResources.resx`. For more information, see [The Resources File](the_resources_file.md). -**For Windows 10\ Windows 7\ Windows 8**: +## The plug-in package path -* Var:PluginPackedPath * +For Var:ProductName to detect and extract the plug-in package, the following folders must exist: -and +- `Var:PluginPackedPath` +- `Var:PluginUnpackedPath` -* Var:PluginUnpackedPath * +Place the `.sdlplugin` file in the `Packages` subfolder, and then start Var:ProductName. During startup, Var:ProductName automatically extracts the package contents to the `Unpacked` subfolder. -Make sure that you place the **.sdlplugin* file into the sub-folder Packages and launch Var:ProductName. During startup of Var:ProductName the content of the package will be automatically extracted to the Unpacked sub-folder, as illustrated below: +The package folder does not need to match your build output path, but using it as the build output path is convenient because the build writes the `.sdlplugin` file directly to the required location. After you create the plug-in from the empty template, you can already build the project, although it will not provide any functionality yet. -The above folder does not have to be the build output path, but it is convenient to build the project in this folder, as this will also create the **.sdlplugin* file where it needs to be. After creating the plug-in based on the (empty) template, you could already build the project. However, it will, of course, not offer any functionality. - -Upon start-up Var:ProductName will load the unpacked plug-in and show the following message, which you can confirm with **Yes**, so that the plug-in gets loaded. This message appears when loading plug-ins that have not been certified by RWS, which could potentially be unsafe. The message can be avoided by submitting your plug-in to RWS for certification. +When Var:ProductName starts, it loads the unpacked plug-in and displays the following message. Click **Yes** to load the plug-in. Var:ProductName shows this message for plug-ins that RWS has not certified and that could therefore be unsafe. You can avoid this prompt by submitting your plug-in to RWS for certification. ![NativeFilterWarning](images/NativeFilterWarning.jpg) >[!NOTE] > ->If a user clicks **No** when the plug-in security message is displayed during start-up of Var:ProductName, the plug-in will not be shown in the application. +> If a user clicks **No** when Var:ProductName displays the plug-in security message during startup, the application does not load the plug-in. -After loading the plug-in in Var:ProductName, you can confirm that the plug-in has been added by raising the corresponding dialog box through the menu command **Tools** -> **Plug-ins**. The **Plug-ins** dialog box should list the name of your newly created plug-in: +After Var:ProductName loads the plug-in, open **Tools** > **Plug-ins** to confirm that the application added it. The **Plug-ins** dialog box should list your new plug-in: ![PlugInList](images/PlugInList.jpg) -The Plug-in Manifest --- -One essential piece of information required in order to build the plug-in package this is the plug-in package manifest, which is defined in the file **pluginpackage.manifest.xml**. This file is part of the project template. If this manifest is missing, the project package cannot be built. +## The plug-in manifest + +The plug-in package requires a manifest file named `pluginpackage.manifest.xml`. The project template includes this file. If the manifest is missing, the build cannot create the plug-in package. -Below you see what the manifest of our sample plug-in looks like: +The following example shows the manifest for the sample plug-in: -# [Xml](#tab/tabid-1) ```xml @@ -56,37 +50,33 @@ Below you see what the manifest of our sample plug-in looks like: 1.0 Sdl.Sdk.FileTypeSupport.Samples.SimpleText - + ``` -*** -The manifest contains the following information: -* **PlugInName**: indicates the friendly name of the plugin. This string be different from the name of the plug-in that is defined in PluginResources.resx. The reason for this is that a plug-in package can - in theory - contain multiple plug-ins, which need to be distinguished. -* **Version**: the version of the plug-in package. This information is used to detect any package updates upon start-up of Var:ProductName, and is therefore important. -* **Description**: descriptive information of the plug-in package. -* **Author**: the name of the plug-in developer. -* **RequiredProduct**: this string indicates which RWS product version is required to run the given plug-in. The information that you indicate here must include the minimum version, and can optionally include a maximum version. +The manifest contains the following elements: + +- **PlugInName**: Specifies the friendly name of the plug-in. This value can differ from the plug-in name defined in `PluginResources.resx` because one plug-in package can theoretically contain multiple plug-ins. +- **Version**: Specifies the version of the plug-in package. Var:ProductName uses this value to detect package updates during startup. +- **Description**: Describes the plug-in package. +- **Author**: Identifies the plug-in developer. +- **RequiredProduct**: Specifies the RWS product version required to run the plug-in. You must provide a minimum version, and you can optionally provide a maximum version. -Build and Debug Suggestions --- +## Build and debug suggestions -Here are a couple of simple suggestions to help buld and debug your plug-in. +Use the following suggestions to simplify building and debugging your plug-in: -* Change your solution and project so that it runs Var:ProductName by default. -* Change your project so that it the output is directed to the Var:ProductName plug-in package directory - this will automatically deploy your plug-in. In Windows 7, the Var:ProductNameplug-in package directory is stored in Var:PluginPackedPath. -* Change your project so that it deletes the previous unpacked version of your plug-in - this will ensure that Studio uses the latest version of your plug-in. This can be done using a post-build event. +- Configure the solution and project to start Var:ProductName by default. +- Configure the project output path to the Var:ProductName plug-in package directory. This setting deploys your plug-in automatically. Var:PluginPackedPath stores the package directory path. +- Delete the previous unpacked version of your plug-in during the build. This step ensures that Var:ProductName uses the latest version. You can do this with a post-build event. ```txt rmdir /S /Q "Var:PluginUnpackedPath \Sdl.Sdk.FileTypeSupport.Samples.Bil" ``` -See Also --- - - -[Creating a New Project](creating_a_new_project.md) +## See also +- [Creating a New Project](creating_a_new_project.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/create_a_bilingual_verifier_introduction.md b/apiconcepts/filetypesupport/create_a_bilingual_verifier_introduction.md index 3bd14269e8..079d9f9b63 100644 --- a/apiconcepts/filetypesupport/create_a_bilingual_verifier_introduction.md +++ b/apiconcepts/filetypesupport/create_a_bilingual_verifier_introduction.md @@ -1,29 +1,27 @@ -Introduction -=== +# Introduction -This guide will walk you step by step through the creation of a C# project in Var:VisualStudioEdition for developing a simple bilingual verification plug-in. +This guide steps you through creating a C# project in Var:VisualStudioEdition to develop a simple bilingual verification plug-in. -Imagine that you need to translate Microsoft Word 2007 documents that contain WordArt objects. Let us assume that the translations for these WordArt objects should not exceed a certain number of words. The purpose is, for example, to keep headlines and slogans as short, crisp and catchy as possible. +## Scenario -The scenario for our sample project is to enhance the standard Microsoft Word 2007 File Type Component Builder to include a bilingual verification plug-in that points out any WordArt translations that exceed a specified maximum word count. The maximum word count needs to be user-definable. +You're translating Microsoft Word 2007 documents that contain WordArt objects. You need to ensure WordArt translations don't exceed a specified word count. This keeps headlines and slogans short, crisp, and catchy. + +This sample project enhances the standard Microsoft Word 2007 File Type Component Builder with a bilingual verification plug-in. The plug-in identifies any WordArt translations that exceed a user-definable maximum word count. ![WordArt](images/WordArt.jpg) -The illustration above shows what the sample document looks like in Var:ProductName. Note that in the above example the first and the last segment were extracted from WordArt objects. +The illustration shows the sample document in Var:ProductName. The first and last segments were extracted from WordArt objects. -The document structure column on the right-hand side contains the context info **TAG**, which indicates that the corresponding segment does not occur in a normal paragraph. By double-clicking the **TAG** display code you raise a **Document Structure Information** window, which contains more details such as the information that the current **TAG** text is a WordArt object. The following chapters contain a step-by-step guide on how to implement a simple bilingual verification plug-in in C# that performs a word count check in particular for WordArt objects. +The document structure column on the right displays the context info **TAG**, which indicates that the segment does not occur in a normal paragraph. Double-click the **TAG** display code to open a **Document Structure Information** window with more details, such as information that identifies the current **TAG** text as a WordArt object. ![DocStructureInfo](images/DocStructureInfo.jpg) -See Also --- - - +The following chapters step you through implementing a simple bilingual verification plug-in in C# that performs a word count check specifically for WordArt objects. -[What is the Verification Framework?](what_is_the_verification_framework.md) +## See Also -[Create a New Project](create_a_new_bil_project.md) +- [What is the Verification Framework?](what_is_the_verification_framework.md) +- [Create a New Project](create_a_new_bil_project.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/create_a_native_verifier_introduction.md b/apiconcepts/filetypesupport/create_a_native_verifier_introduction.md index 86566260f7..306e966180 100644 --- a/apiconcepts/filetypesupport/create_a_native_verifier_introduction.md +++ b/apiconcepts/filetypesupport/create_a_native_verifier_introduction.md @@ -1,14 +1,12 @@ -Introduction -=== +# Introduction -This guide will walk you through the creation of a C# project in Var:VisualStudioEdition for implementing a simple native verifier that works on XML documents. +This guide steps you through creating a C# project in Var:VisualStudioEdition to implement a simple native verifier that works on XML documents. -The Sample Scenario --- +## The Sample Scenario -Native verifiers do not work on the intermediary (SDLXliff) files, but on the native document output. For this sample project let us imagine the following scenario: +Native verifiers work on native document output, not on intermediary (SDLXliff) files. For this sample project, consider this scenario: -You need to localize XML files that looks as shown below: +You're localizing XML files with the following structure: # [Xml](#tab/tabid-1) ```xml @@ -20,21 +18,15 @@ You need to localize XML files that looks as shown below: ``` -*** -Note that the ```displaytext``` element contains the attribute ```maxlength```, which specifies the maximum length of the text that is enclosed in this tag pair. Image that you need to develop a verification plug-in that checks whether the length limit specified in this attribute has been adhered to during translation. +The `displaytext` element contains a `maxlength` attribute that specifies the maximum length of the enclosed text. Develop a verification plug-in that checks whether translations adhere to this length limit. -You will find the complete Visual Studio project for this plug-in in the **Sdl.Sdk.FilterFramework.Samples.XMLChecker** sub-directory of the samples folder. This directory also contains a small sample XML file (**XMLCheckerTestFile.xml**) and a new file type definition (**Length Check XML v 1.0.0.0**) that uses this verification plug-in. +The complete Visual Studio project for this plug-in is in the **Sdl.Sdk.FilterFramework.Samples.XMLChecker** subdirectory of the samples folder. This directory also contains a sample XML file (**XMLCheckerTestFile.xml**) and a file type definition (**Length Check XML v 1.0.0.0**) that uses this verification plug-in. -See Also --- +## See Also +- [What is the Verification Framework?](what_is_the_verification_framework.md) +- [Create a New Project](create_a_new_native_project.md) - -[What is the Verification Framework?](what_is_the_verification_framework.md) - -[Create a New Project](create_a_new_native_project.md) - ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/create_a_new_bil_project.md b/apiconcepts/filetypesupport/create_a_new_bil_project.md index 27c6488543..86cfb807c4 100644 --- a/apiconcepts/filetypesupport/create_a_new_bil_project.md +++ b/apiconcepts/filetypesupport/create_a_new_bil_project.md @@ -1,30 +1,30 @@ -Create a New Project -=== +# Create a New Project -In this chapter you will learn how to properly set up a project for developing a verification plug-in that works on the bilingual (SDLXliff) file format. +Learn how to properly set up a project for developing a verification plug-in that works on the bilingual (SDLXliff) file format. -Create the Project --- +## Create the Project -After launching Var:VisualStudioEdition choose to create a new Var:ProductName Plug-in Project, and give it an appropriate name, e.g. Sdl.Sdk.FileTypeSupport.Samples.WordArtVerifier. The instructions for creating a Var:ProductName Plug-in Project are described in the [**Building a Plug-in**](../../articles/gettingstarted/building_a_plugin.md) article under the **Getting Started** section. +Launch Var:VisualStudioEdition and create a new Var:ProductName Plug-in Project. Give it an appropriate name, such as `Sdl.Sdk.FileTypeSupport.Samples.WordArtVerifier`. -A Var:ProductName Plug-in Project produces a Plug-in Package (* *.sdlplugin*). This needs to be manually deployed or copied to the Var:ProductName Plug-in Packages directory so that Var:ProductName can use the plug-in. See the [**Plug-in Deployment**](../../articles/gettingstarted/plugin_deployment.md) article under the **Getting Started** section. +For instructions on creating a Var:ProductName Plug-in Project, see the [Building a Plug-in](../../articles/gettingstarted/building_a_plugin.md) article in the **Getting Started** section. -Add the Required References --- +A Var:ProductName Plug-in Project produces a Plug-in Package (`*.sdlplugin`). You must manually deploy or copy this package to the Var:ProductName Plug-in Packages directory so that Var:ProductName can use the plug-in. For deployment instructions, see the [Plug-in Deployment](../../articles/gettingstarted/plugin_deployment.md) article in the **Getting Started** section. -Next add the references from the File Type Support Framework APIs. These are contained in the following assemblies: +## Add the Required References -* **Sdl.FileTypeSupport.Framework.Core.dll**: This is the main reference to the File Type Support Framework API -* **Sdl.FileTypeSupport.Framework.Core.Settings.dll** +Add references from the File Type Support Framework APIs. These references are contained in the following assemblies: -Then add the references from the Core APIs. -* **Sdl.Core.Settings.dll** -* **Sdl.Core.PluginFramework.dll** -By default you will find these files in the Var:ProductName installation folder, e.g. *Var:InstallationFolder*. The **Copy Local** property for these references should be set to True. +- **Sdl.FileTypeSupport.Framework.Core.dll** — The main reference to the File Type Support Framework API +- **Sdl.FileTypeSupport.Framework.Core.Settings.dll** + +Add references from the Core APIs: + +- **Sdl.Core.Settings.dll** +- **Sdl.Core.PluginFramework.dll** + +By default, these files are in the Var:ProductName installation folder (for example, *Var:InstallationFolder*). Set the **Copy Local** property for these references to True. ![BilingualVerifierReferences](images/BilingualVerifierReferences.jpg) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/create_a_new_native_project.md b/apiconcepts/filetypesupport/create_a_new_native_project.md index d5395074e2..ef929eac86 100644 --- a/apiconcepts/filetypesupport/create_a_new_native_project.md +++ b/apiconcepts/filetypesupport/create_a_new_native_project.md @@ -1,31 +1,30 @@ -Create a New Project -=== +# Create a New Project -In this chapter you will learn how to properly set up a project for developing a verification plug-in that works on the native file format. +Learn how to properly set up a project for developing a verification plug-in that works on the native file format. -Create the Project --- +## Create the Project -After launching Var:VisualStudioEdition choose to create a new Var:ProductName Plug-in Project, and give it an appropriate name, e.g. *Sdl.Sdk.FileTypeSupport.Samples.XMLChecker*. The instructions for creating a Var:ProductName Plug-in Project are described in the [**Building a Plug-in**](../../articles/gettingstarted/building_a_plugin.md) article under the **Getting Started** section. +Launch Var:VisualStudioEdition and create a new Var:ProductName Plug-in Project. Give it an appropriate name, such as `Sdl.Sdk.FileTypeSupport.Samples.XMLChecker`. -Var:ProductName Plug-in Project produces a Plug-in Package (.sdlplugin). This needs to be manually deployed or copied to the Var:ProductName Plug-in Packages directory so that Var:ProductName can use the plug-in. See the [**Plug-in Deployment**](../../articles/gettingstarted/plugin_deployment.md) article under the **Getting Started** section. +For instructions on creating a Var:ProductName Plug-in Project, see the [Building a Plug-in](../../articles/gettingstarted/building_a_plugin.md) article in the **Getting Started** section. -Add the Required References --- +A Var:ProductName Plug-in Project produces a Plug-in Package (`*.sdlplugin`). You must manually deploy or copy this package to the Var:ProductName Plug-in Packages directory so that Var:ProductName can use the plug-in. For deployment instructions, see the [Plug-in Deployment](../../articles/gettingstarted/plugin_deployment.md) article in the **Getting Started** section. -Next add the references from the File Type Support Framework APIs. These are contained in the following assemblies: +## Add the Required References -* **Sdl.FileTypeSupport.Framework.Core.dll**: This is the main reference to the File Type Support Framework API -* **Sdl.FileTypeSupport.Framework.Core.Settings.dll** +Add references from the File Type Support Framework APIs. These references are contained in the following assemblies: -Then add the references from the Core APIs. -* **Sdl.Core.Settings.dll** -* **Sdl.Core.PluginFramework.dll** +- **Sdl.FileTypeSupport.Framework.Core.dll** — The main reference to the File Type Support Framework API +- **Sdl.FileTypeSupport.Framework.Core.Settings.dll** -By default you find these files in the Var:ProductName installation folder, usually *Var:InstallationFolder*. The **Copy Local** property for these references should be set to True. +Add references from the Core APIs: + +- **Sdl.Core.Settings.dll** +- **Sdl.Core.PluginFramework.dll** + +By default, these files are in the Var:ProductName installation folder (usually *Var:InstallationFolder*). Set the **Copy Local** property for these references to True. ![NativeVerifierReferences](images/NativeVerifierReferences.jpg) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/create_new_file_type_component_builder.md b/apiconcepts/filetypesupport/create_new_file_type_component_builder.md index 7d1cb94b4c..1e89516f6d 100644 --- a/apiconcepts/filetypesupport/create_new_file_type_component_builder.md +++ b/apiconcepts/filetypesupport/create_new_file_type_component_builder.md @@ -1,26 +1,22 @@ -Create a New File Type Component Builder -=== +# Create a New File Type Component Builder ->[!NOTE] -> ->This functionality is only available in Studio 2011 SP3. +> [!NOTE] +> This functionality is only available in Studio 2011 SP3. -This chapter provides basic information on extending a standard Microsoft Word 2007 File Type Component Builder so the WordArt bilingual verifier will be used. +Extend the standard Microsoft Word 2007 File Type Component Builder so the WordArt bilingual verifier is used. -Extending a Microsoft Word 2007 File Type Component Builder --- +## Extend a Microsoft Word 2007 File Type Component Builder -As Microsoft Word 2007 is one of the standard formats supported by Var:ProductName, the corresponding File Type Component Builder already exists. This File Type Component Builder will be used to create an extension for Microsoft Word 2007 File Type Component Builder that uses the WordArt bilingual verifier. +Var:ProductName includes the standard Microsoft Word 2007 format, so the corresponding File Type Component Builder already exists. Use this as the basis for creating an extension that includes the WordArt bilingual verifier. -A File Type Component Builder is defined by a filter component builder that implements [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). A filter component builder knows how to create parsers, writers, and so on for the corresponding file type. Microsoft Word 2007 File Type Component Builder has a filter component builder. +A File Type Component Builder is defined by a filter component builder that implements [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). The filter component builder knows how to create parsers, writers, and other components for the corresponding file type. The Microsoft Word 2007 File Type Component Builder has its own filter component builder. -The Microsoft Word 2007 File Type Component Builder can be inherited from indirectly. To create an extension for the The Microsoft Word 2007 File Type Component Builder you need to implement the [IFileTypeComponentBuilderAdapter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilderAdapter.yml) interface which is used to define *Word 2007 v 2.0.0.0* documents. +To extend the Microsoft Word 2007 File Type Component Builder, implement the [IFileTypeComponentBuilderAdapter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilderAdapter.yml) interface, which is used to define *Word 2007 v 2.0.0.0* documents. ->[!NOTE] -> ->In Var:ProductName all the file type plug-in components are designed in a way that you can extend all the functionality. +> [!NOTE] +> In Var:ProductName, all file type plug-in components are designed to be extensible, so you can extend all functionality. -Every filter component builder extension needs to have a [FileTypeComponentBuilderExtensionAttribute](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.FileTypeComponentBuilderExtensionAttribute.yml) that describes the file type component builder. +Every filter component builder extension requires a [FileTypeComponentBuilderExtensionAttribute](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.FileTypeComponentBuilderExtensionAttribute.yml) that describes the file type component builder: # [C#](#tab/tabid-1) ```cs @@ -30,9 +26,8 @@ Every filter component builder extension needs to have a [FileTypeComponentBuild Description = "Word2007_FilterComponentBuilderExtension_WordArtVerifier_Description", OriginalFileType = "Word 2000-2003 v 1.0.0.0")] ``` -*** -"Word2007_FilterComponentBuilderExtension_WordArtVerifier_Name" and "Word2007_FilterComponentBuilderExtension_WordArtVerifier_Description" refers to entries in the **PlugInResources.resx** file. +The `Word2007_FilterComponentBuilderExtension_WordArtVerifier_Name` and `Word2007_FilterComponentBuilderExtension_WordArtVerifier_Description` values refer to entries in the **PlugInResources.resx** file: # [Xml](#tab/tabid-2) ```xml @@ -43,9 +38,8 @@ Every filter component builder extension needs to have a [FileTypeComponentBuild Word 2007 Filter Component Builder WordArt Verifier ``` -*** -This new component builder needs to be changed so it includes the new WordArt bilingual verifier. This can be accomplished simply by calling the original **BuildVerifierCollection** and adding the new verifier to this collection. +Modify the new component builder to include the WordArt bilingual verifier. Call the original `BuildVerifierCollection` and add the new verifier to the collection: # [C#](#tab/tabid-3) ```cs @@ -56,9 +50,8 @@ public IVerifierCollection BuildVerifierCollection(string name) return verifierCollection; } ``` -*** -This new file type definition also needs to be changed so it includes the new WordArt bilingual verifier settings page. This is accomplished by calling the original **BuildFileTypeInformation** and adding the settings page to **WinFormSettingsPageIds**. +Modify the file type definition to include the WordArt bilingual verifier settings page. Call the original `BuildFileTypeInformation` and add the settings page to `WinFormSettingsPageIds`: # [C#](#tab/tabid-4) ```cs @@ -71,12 +64,10 @@ public IFileTypeInformation BuildFileTypeInformation(string name) fileTypeInformation.WinFormSettingsPageIds = winFormSettingsPageIds.ToArray(); return fileTypeInformation; - } ``` -*** -Here is the complete code for creating a new file type definition based upon the Microsoft Word 2007 file type definition using the new WordArt bilingual verifier. +The following code shows the complete implementation of a new file type definition based on the Microsoft Word 2007 file type definition with the WordArt bilingual verifier: # [C#](#tab/tabid-5) ```cs @@ -104,7 +95,6 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier fileTypeInformation.WinFormSettingsPageIds = winFormSettingsPageIds.ToArray(); return fileTypeInformation; - } public IVerifierCollection BuildVerifierCollection(string name) @@ -172,19 +162,17 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier } } ``` -**** - -Adding a verifier by creating a new file type definition based upon an existing file type definition can be quite effective but suffers one important limitation. In this example, if the user created an *sdlxliff* file based upon a Microsoft Word 2007 document **before** the new file type definition was added then any operations performed on this *sdlxliff* file will use the old Microsoft Word 2007 file type definition and that means that it will not use the WordArt bilingual verifier. Only if the user created an *sdlxliff* file based upon a Microsoft Word 2007 document **after** the new file type definition was added will the new file type definition and therefore the new bilingual verifier be used. -See Also --- +## Important Considerations +Creating a new file type definition based on an existing file type definition offers an effective approach but has one important limitation. If users create an SDLXliff file from a Microsoft Word 2007 document **before** you add the new file type definition, operations on that SDLXliff file use the old Microsoft Word 2007 file type definition. The new WordArt bilingual verifier won't be used. +Only if users create an SDLXliff file from a Microsoft Word 2007 document **after** you add the new file type definition will Var:ProductName use the new file type definition and the new bilingual verifier. -[Implement the Verification Logic](implement_the_verification_logic_bil.md) +## See Also -[Extending the Filter Component Builder](extending_existing_file_type_component_builder.md) +- [Implement the Verification Logic](implement_the_verification_logic_bil.md) +- [Extending the Filter Component Builder](extending_existing_file_type_component_builder.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/creating_a_native_file_tweaker.md b/apiconcepts/filetypesupport/creating_a_native_file_tweaker.md index 004d77bcec..bfba39b6e7 100644 --- a/apiconcepts/filetypesupport/creating_a_native_file_tweaker.md +++ b/apiconcepts/filetypesupport/creating_a_native_file_tweaker.md @@ -1,50 +1,49 @@ -Creating a Native File Tweaker -=== +# Creating a Native File Tweaker -In this chapter, you will learn how to create a native file tweaker. A native file tweaker can either tweak - or perform a minor change to - the original file before being extracted (a pre-tweaker) or tweak the output file after being written (a post-tweaker). See [Native File Tweakers](native_file_tweakers.md) for more information. +Create native file tweakers that modify the original file before extraction (pre-tweaker) or the output file after generation (post-tweaker). See [Native File Tweakers](native_file_tweakers.md) for more information. -Native file tweakers make use of the following namespaces: +Native file tweakers use the following namespaces: -* [Sdl.FileTypeSupport.Framework.NativeApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.yml) -* [Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.yml) +- [Sdl.FileTypeSupport.Framework.NativeApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.yml) +- [Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.yml) -These namespaces should be used and the associated assembly references added when developing native file tweakers. +Add references to these assemblies when developing native file tweakers. # [C#](#tab/tabid-1) ```cs using Sdl.FileTypeSupport.Framework.NativeApi; using Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi; ``` -*** -Creating a Native File Pre-Tweaker --- +## Creating a Native File Pre-Tweaker -A simple native file pre-tweaker will be developed to remove the byte order mark from the original file before being extracted. +Develop a simple native file pre-tweaker that removes the byte order mark from the original file before extraction. -Native file pre-tweakers should inherit from [AbstractFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml). +Pre-tweakers inherit from [AbstractFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml). # [C#](#tab/tabid-2) ```cs public class SimpleFilePreTweaker : AbstractFilePreTweaker ``` -*** +### Key Properties -The **properties** parameter contains two important properties: +The `properties` parameter contains two important properties: -* [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath) is the file path of the original native file. -* [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath) is the file path of the tweaked native file. +- [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath) — The file path of the original native file +- [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath) — The file path of the tweaked native file -The [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_) method is where the native file is tweaked. An implementation of this method should read the original native file, perform some processing, and create and write the tweaked native file to [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath). The tweaker is only responsible for creating the tweaked native file; it is not responsible for deleting the tweaked native file after processing. +### The Tweak Method -In this example, the implementation of the [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_) method that removes the byte order mark is quite straightforward and consists of the following steps: +The [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_) method performs the tweaking. Read the original native file from `OriginalFilePath`, process it, and write the tweaked file to `InputFilePath`. The framework handles deletion of the tweaked file after processing. -1. Open the original file using [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath) as the file path. -2. Create the tweaked file with UTF-8 encoding without the byte order mark using [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath) as the file path. -3. Copy the lines from the original file to the tweaked file. +This example removes the byte order mark with these steps: -Add the following code to the [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_) method. +1. Open the original file using `OriginalFilePath` +2. Create the tweaked file with UTF-8 encoding without the byte order mark using `InputFilePath` +3. Copy lines from the original file to the tweaked file + +Add the following code to the [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_) method: # [C#](#tab/tabid-3) ```cs @@ -63,30 +62,25 @@ using (StreamReader reader = new StreamReader(properties.OriginalFilePath)) } } ``` -*** -[AbstractFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml) has a [WillFileBeTweaked](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_WillFileBeTweaked_System_String_) method that may be overridden. +### The WillFileBeTweaked Method + +Override the [WillFileBeTweaked](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_WillFileBeTweaked_System_String_) method to optimize performance. Return `false` when the file doesn't need tweaking, preventing unnecessary file operations. # [C#](#tab/tabid-4) ```cs protected override bool WillFileBeTweaked(string originalFilePath) ``` -*** - -There may be some circumstances where the original native file does not need to be tweaked and in these circumstances the [WillFileBeTweaked](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_WillFileBeTweaked_System_String_) method should return **false** to prevent the original native file from being tweaked. -Here the original native file only needs to be tweaked if the original native file has a byte order. -Add the following code to the [WillFileBeTweaked](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_WillFileBeTweaked_System_String_) method. +In this example, the file only needs tweaking if it has a byte order mark. Add this code to the method: # [C#](#tab/tabid-5) ```cs // if original file has a byte order mark then the original file needs to be tweaked return HasByteOrderMark(originalFilePath); ``` -*** - -Add the following method that determines whether a given file has a byte order mark to the **SimpleFilePreTweaker** class. +Add the helper method that checks for a byte order mark to the `SimpleFilePreTweaker` class: # [C#](#tab/tabid-6) ```cs @@ -113,33 +107,40 @@ private bool HasByteOrderMark(string filePath) } } ``` -*** +This completes the native file pre-tweaker that removes the byte order mark from the original file. + +### Parser Implementation Implications -That completes this simple native file pre-tweaker which removes the byte order mark from the original native file. +Pre-tweakers read from `OriginalFilePath` and write to `InputFilePath`. This affects how parsers should read files: parsers must read from `InputFilePath`, not `OriginalFilePath`. This allows parsers to work with tweaked files. If no tweaker exists or the tweaker determines the file doesn't need tweaking, the framework sets `InputFilePath` to `OriginalFilePath`. -The way native file pre-tweakers work affects the way parsers should be implemented. Any native file pre-tweaker works by reading the original native file from [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath) and writing a tweaked native file to [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath). This has an important consequence for any parsers. Any parser should read from [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath) rather than [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath) because this allows the parser to read from tweaked files. If a file has not been tweaked either because a tweaker does not exist or the tweaker reported that the file did not need tweaking then [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath) will be set to [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath). +## Creating a Native File Post-Tweaker +Develop a simple native file post-tweaker that adds the byte order mark to the output file after generation. Post-tweakers are similar to pre-tweakers and inherit from [AbstractFilePostTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml). -Creating a Native File Post-Tweaker --- +Override the [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePostTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_) method in your post-tweaker. -A simple native file post-tweaker will be developed to add the byte order mark to the output file after being written. A native file post-tweaker is similiar to a native file pre-tweaker. Native file post-tweakers should inherit from [AbstractFilePostTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml) which has a [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePostTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_) method that must be overridden. +### Key Differences from Pre-Tweaker -The [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePostTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_) method has a **properties** parameter that contains one property that concerns us here: +The `properties` parameter contains: -* [OutputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputFileProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_OutputFilePath) is the file path of the output native file. +- [OutputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputFileProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_OutputFilePath) — The file path of the output native file -One important difference between a native file pre-tweaker and a native file post-tweaker is that whilst the pre-tweaker reads the original file from [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath) and writes the tweaked file to [InputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_InputFilePath), the post-tweaker reads the original file and writes the tweaked file to [OutputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputFileProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_OutputFilePath) . Another important difference is that the native file post-tweaker does not have the [WillFileBeTweaked](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePreTweaker_WillFileBeTweaked_System_String_) method. +Key differences from pre-tweakers: -In this example, the implementation of the [Tweak](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml#Sdl_FileTypeSupport_Framework_Core_Utilities_NativeApi_AbstractFilePostTweaker_Tweak_Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_) method that adds the byte order mark is quite straightforward and consists of the following steps: +- Pre-tweakers read from `OriginalFilePath` and write to `InputFilePath`; post-tweakers read from and write to `OutputFilePath` +- Post-tweakers don't have the `WillFileBeTweaked` method -1. Open the original file using the original output file path; [OutputFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputFileProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeOutputFileProperties_OutputFilePath) . -2. Create the tweaked file with UTF-8 encoding with the byte order mark using a temporary file path. -3. Copy the lines from the original file to the tweaked file. -4. Replace the original file with the tweaked file. +### Implementing the Post-Tweaker Tweak Method -Here is the complete simple native file post-tweaker code which adds the byte order mark to the original native file. +This example adds the byte order mark with these steps: + +1. Read the output file from `OutputFilePath` +2. Create a tweaked file with UTF-8 encoding with the byte order mark using a temporary file +3. Copy lines from the original file to the tweaked file +4. Replace the original file with the tweaked file + +Here's the complete native file post-tweaker that adds the byte order mark: # [C#](#tab/tabid-7) ```cs @@ -183,15 +184,10 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText } } ``` -*** - -See Also --- - +## See Also -[Native File Tweakers](native_file_tweakers.md) +- [Native File Tweakers](native_file_tweakers.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/creating_a_new_assembly_for_the_settings_ui.md b/apiconcepts/filetypesupport/creating_a_new_assembly_for_the_settings_ui.md index f59fcabf85..b05a84bb47 100644 --- a/apiconcepts/filetypesupport/creating_a_new_assembly_for_the_settings_ui.md +++ b/apiconcepts/filetypesupport/creating_a_new_assembly_for_the_settings_ui.md @@ -1,50 +1,39 @@ -Creating a New Assembly for the Settings UI -=== +# Creating a New Assembly for the Settings UI -In this chapter we will show you how to create a separate project for adding a user interface to our file type plug-in. +Create a separate project for adding a user interface to your file type plug-in. -Create a New Project --- +## Create a New Project -Let us assume that you want to add a user interface to your file type plug-in, so that users can configure certain options at runtime. Example: suppose that sometimes the product code lines need to be locked, but sometimes they may require localization. So, users should be able to make this determination on a case-by-case basis for each document. +To expose runtime configuration options to users, create a separate assembly for the UI. This allows you to build different user interfaces for the same file type plug-in—for example, a desktop UI or a web-based UI. -In order to achieve this you need to expose a configurable setting to a user interface. Based on the setting applied to the user interface the file parser should later lock the product code lines or expose them for translation. +Consider this scenario: sometimes product code lines need to be locked, and sometimes they require localization. Users should determine this case-by-case for each document. Based on the user's setting in the UI, the file parser locks or exposes product code lines for translation. -Rather than adding a user interface control to your existing project, you should create a second project for building a separate UI assembly. The reason for this is that you can build different user interfaces for the same file type plug-in. For example, you could have a desktop-based user interface as well as a Web-based UI. - -For the type of plug-in discussed in this chapter, we require the **Var:ProductName Plug-in Project** template. +Rather than adding UI controls to your existing project, create a second project for the UI assembly. This separation enables flexible UI implementations. +For this plug-in, use the **Var:ProductName Plug-in Project** template. ![PluginTemplate](images/PluginTemplate.jpg) +By default, the project name will be **Var:ProductName Plug-in Project1**. Change it to `Sdl.Sdk.FileTypeSupport.Samples.SimpleText.WinUI` for this sample. -By default, when you create a project based on this template, the project name will be e.g. **Var:ProductName Plug-in Project1**. Change the project name to **Sdl.Sdk.FileTypeSupport.Samples.SimpleText.WinUI** for our sample implementation. - -Add the Required References --- - -The plug-in template will come with the **Sdl.Core.PluginFramework.dll** reference. - -Now add the following libraries as references to the new UI project: - -* **Sdl.Core.Settings.dll** -* **Sdl.FileTypeSupport.Framework.Core.Settings.dll** +## Add the Required References -Set the output path for building your project to the installation folder of Var:ProductName, e.g. *Var:InstallationFolder*. +The plug-in template includes the **Sdl.Core.PluginFramework.dll** reference. -See Also --- +Add the following libraries as references to the UI project: +- **Sdl.Core.Settings.dll** +- **Sdl.FileTypeSupport.Framework.Core.Settings.dll** +Set the project's output path to the Var:ProductName installation folder (for example, *Var:InstallationFolder*). -[Implementing the Settings UI](implementing_the_settings_ui.md) +## See Also -[Implementing the UI Controller Class](implementing_the_ui_controller_class.md) +- [Implementing the Settings UI](implementing_the_settings_ui.md) +- [Implementing the UI Controller Class](implementing_the_ui_controller_class.md) ->[!NOTE] -> ->Remember to generate a key to sign the assembly. +> [!NOTE] +> Remember to generate a key to sign the assembly. ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/creating_a_new_bil_project.md b/apiconcepts/filetypesupport/creating_a_new_bil_project.md index 8ad3895cab..a251975f1b 100644 --- a/apiconcepts/filetypesupport/creating_a_new_bil_project.md +++ b/apiconcepts/filetypesupport/creating_a_new_bil_project.md @@ -1,40 +1,38 @@ -Creating a New Project -=== +# Creating a New Project -In this chapter you will learn how to properly set up a project for developing a bilingual file type plug-in. +Learn how to properly set up a project for developing a bilingual file type plug-in. -Create the Project --- +## Create the Project -After launching Var:VisualStudioEdition choose to create a new Var:ProductName Plug-in Project, and give it an appropriate name, e.g. *Sdl.Sdk.FileTypeSupport.Samples.Bil*. The instructions for creating a Var:ProductName Plug-in Project are described in the [Creating a New Project](creating_a_new_project.md) and [Build the File Type Plug-in](build_the_file_type_plug_in.md) topics. +Launch Var:VisualStudioEdition and create a new Var:ProductName Plug-in Project. Give it an appropriate name, such as `Sdl.Sdk.FileTypeSupport.Samples.Bil`. -Add the Required References --- +For instructions on creating a Var:ProductName Plug-in Project, see the [Creating a New Project](creating_a_new_project.md) and [Build the File Type Plug-in](build_the_file_type_plug_in.md) topics. -Next add the references from the File Type Support Framework APIs. These are contained in the following assemblies: +## Add the Required References -* **Sdl.FileTypeSupport.Framework.Core.dll**: This is the main reference to the File Type Support Framework API -* **Sdl.FileTypeSupport.Framework.Core.Settings.dll** -* **Sdl.FileTypeSupport.Framework.Core.Utilities.dll** +Add references from the File Type Support Framework APIs. These references are contained in the following assemblies: -Then add the references from the Core APIs. -* **Sdl.Core.Globalization.dll** -* **Sdl.Core.PluginFramework.dll** -* **Sdl.Core.Settings.dll** +- **Sdl.FileTypeSupport.Framework.Core.dll** — The main reference to the File Type Support Framework API +- **Sdl.FileTypeSupport.Framework.Core.Settings.dll** +- **Sdl.FileTypeSupport.Framework.Core.Utilities.dll** -By default you find these files in the Var:ProductName installation folder, usually *Var:InstallationFolder*. The **Copy Local** property for these references should be set to True. +Add references from the Core APIs: -Remember to generate a key to sign the assembly. It is also recommended that you set **SDLTradosStudio.exe** as the external application for debugging purposes. +- **Sdl.Core.Globalization.dll** +- **Sdl.Core.PluginFramework.dll** +- **Sdl.Core.Settings.dll** -Add the Required Resources --- +By default, these files are in the Var:ProductName installation folder (usually *Var:InstallationFolder*). Set the **Copy Local** property for these references to True. -Add a resources file (*Resources.resx*) to the project's properties. We will use this resources file later for storing information text on the file type plug-in that will be exposed in the user interface of Var:ProductName. +Generate a key to sign the assembly. For debugging, set **SDLTradosStudio.exe** as the external application. + +## Add the Required Resources + +Add a resources file (`Resources.resx`) to the project's properties. Use this resources file for storing file type plug-in information that Var:ProductName displays in the user interface. ![SimpleTextFilterResources](images/SimpleTextFilterResources.jpg) -Add an icon to the project. You will find a suitable icon file (*Bil.ico*) in the folder **Sdl.Sdk.FileTypeSupport.Samples.Bil** of the SDK sample projects folder. Set the **Build Action** property for the icon file to **Embedded Resource**. The icon that you add to the project will be the one that users will later see in the **Options** dialog box of Var:ProductName. +Add an icon to the project. Find a suitable icon file (`Bil.ico`) in the **Sdl.Sdk.FileTypeSupport.Samples.Bil** folder of the SDK sample projects. Set the **Build Action** property for the icon file to **Embedded Resource**. Users see this icon in the **Options** dialog box of Var:ProductName. ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/creating_a_new_project.md b/apiconcepts/filetypesupport/creating_a_new_project.md index 8b26b6db20..a7da2c1faf 100644 --- a/apiconcepts/filetypesupport/creating_a_new_project.md +++ b/apiconcepts/filetypesupport/creating_a_new_project.md @@ -1,39 +1,36 @@ -Creating a New Project -=== -In this chapter you will learn how to properly set up a project for developing a file type plug-in. +# Creating a new project -Create the Project --- +This article shows how to set up a project for developing a file type plug-in. -Before you start developing plug-ins for Var:ProductName, you should make sure that the SDK is installed on your development computer. The SDK installer will add new templates to your Microsoft Visual Studio environment, as illustrated in the screenshot below. For the type of plug-in discussed in this chapter, we require the **Var:ProductName Plug-in Project** template. +## Create the project + +Before you start developing plug-ins for Var:ProductName, make sure that you installed the SDK on your development computer. The SDK installer adds new templates to Visual Studio, as shown in the following screenshot. For the plug-in type covered in this article, use the **Var:ProductName Plug-in Project** template. ![PlugInTemplate](images/PlugInTemplate.jpg) -By default, when you create a project based on this template, the project name will be e.g. **Var:ProductName Plug-in Project1**. Change the project name to **Sdl.Sdk.FileTypeSupport.Samples.SimpleText** for our sample implementation. +By default, Visual Studio assigns a name such as **Var:ProductName Plug-in Project1**. For this sample, rename the project to **Sdl.Sdk.FileTypeSupport.Samples.SimpleText**. -Add the Required References --- +## Add the required references -The plug-in template will come with the **Sdl.Core.PluginFramework.dll** reference. For our file type plug-in implementation, we also need to reference the File Type Support Framework, i.e. **Sdl.FileTypeSupport.Framework.Core.dll**. For implementing the functionality required by our example, you need to add the libraries used for integration with Var:ProductName, which are as follows: +The plug-in template already includes a reference to **Sdl.Core.PluginFramework.dll**. For this file type plug-in, also add a reference to **Sdl.FileTypeSupport.Framework.Core.dll**. To support the functionality in this example, add the following libraries that integrate with Var:ProductName: * **Sdl.FileTypeSupport.Framework.Core.Settings.dll** * **Sdl.Core.Settings.dll** * **Sdl.Core.Globalization.dll** * **Sdl.FileTypeSupport.Framework.Core.Utilities** -By default these files can be found in the installation folder of Var:ProductName, i.e. *Var:InstallationFolder*. The 'Copy Local' property for these references should be set to True. +You can find these files in the Var:ProductName installation folder, that is, `Var:InstallationFolder`. Set the **Copy Local** property for these references to **True**. ![NativeFilterRef](images/NativeFilterRef.jpg) >[!NOTE] > ->Do not forget to sign the assembly. Otherwise, your plug-in might not be loaded by Var:ProductName +> Sign the assembly. Otherwise, Var:ProductName might not load your plug-in. -See Also --- +## See also -[What is the Verification Framework?](what_is_the_verification_framework.md) +- [What is the Verification Framework?](what_is_the_verification_framework.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/creating_projects.md b/apiconcepts/filetypesupport/creating_projects.md index 2a60014ba8..7ee913c066 100644 --- a/apiconcepts/filetypesupport/creating_projects.md +++ b/apiconcepts/filetypesupport/creating_projects.md @@ -1,30 +1,25 @@ -Creating projects -===== -Var:ProductName also allows you to create projects, which is often done by project managers, who assign tasks to translators, editors, etc. Translators can also create projects to process multiple files (e.g. 100 HTML files that make up a website) more easily instead of opening all files one by one. +# Creating projects -In addition to opening single files for processing, users can also create projects. This is useful, for example, when: +Var:ProductName lets translators and project managers create projects for multi-file jobs. Use a project when you need to process many files, assign work to multiple roles, or prepare content for one or more target languages. -* A translator needs to process multiple files (e.g. several dozen HTML files). This is more efficient than opening each file one by one. -* A project manager wants to prepare multiple files for translation into one or several target languages and wants to assign tasks to different users (e.g. English, French, Spanish translators, and editors). +Project creation is wizard-based. In the wizard, users can specify the main project settings: - -Project creation is fully wizard-based. The user can select, among other things, the following main project parameters: * Project name * Due date * Files * Target language(s) * Translation memories and termbases -The project files are processed in what is called a task sequence. A task sequence comprises multiple single tasks such as word count, file analysis, etc. The most important single task is probably the one that converts the native documents into the intermediary format (e.g. SDLXliff). This is a pre-requisite for any subsequent task, as files cannot be translated, analyzed, etc. in Var:ProductName without prior conversion to the intermediate format. +The project wizard processes files through a task sequence. A task sequence includes tasks such as word count and file analysis. It also includes the task that converts source files into the intermediate format, such as SDLXliff. Run that conversion before translation or analysis. - + Entering general project information in the project wizard. - + Applying a batch task sequence to all project files. -See Also ------- +## See also + [Merging files](merging_files.md) diff --git a/apiconcepts/filetypesupport/dynamic_modifying_the_file_type_component_builder.md b/apiconcepts/filetypesupport/dynamic_modifying_the_file_type_component_builder.md index a683bcaec8..78dbae5b4a 100644 --- a/apiconcepts/filetypesupport/dynamic_modifying_the_file_type_component_builder.md +++ b/apiconcepts/filetypesupport/dynamic_modifying_the_file_type_component_builder.md @@ -1,18 +1,20 @@ -Modifying the File Type Component Builder -=== +# Modifying the file type component builder -The real-time preview is dynamic, i.e. it interacts with the editor. When users select a segment in the real-time preview, the corresponding segment in the editor gets highlighted automatically. Also, when users confirm a segment in the editor of Var:ProductName the real-time preview is updated accordingly. Like all other preview types, the real-time preview needs to be referenced in the File Type Component Builder. +The real-time preview interacts with the editor. When users select a segment in the real-time preview, Var:ProductName highlights the corresponding segment in the editor. When users confirm a segment in the editor, the real-time preview updates accordingly. -Add the Real-Time Preview Name to the Resources --- +Like the other preview types, the real-time preview must be referenced in the File Type Component Builder. -To implement the real-time preview we first need to make a few additions to the File Type Component Builder. In the first step, define the preview name in the resources file. This is the name that will be shown later in the combo box of the internal preview window of Var:ProductName. Add the following entires to the resources file, which are going to be referenced in the File Type Component Builder later: +## Add the real-time preview name to the resources + +Start by defining the preview name in the resources file. Var:ProductName displays this name in the internal preview window combo box. The File Type Component Builder references these resource entries later. ![RealtimeStaticPreviewName](images/RealtimeStaticPreviewName.jpg) +## Add the internal real-time preview set + +Next, add the following preview set object for the internal real-time preview to the File Type Component Builder. You can place it below the internal preview set. See [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md). -Add the Internal Real-time Preview Set -In the next step add the following preview set object node for the internal real-time preview into the File Type Component Builder (e.g. below the internal preview set, see chapter [Modifying the File Type Component Builder](static_modifying_the_file_type_component_builder.md)). Note how the object references the preview name that you previously defined in the resources file. After adding the real-time preview set to the File Type Component Builder, the preview name will already be listed in the combo box of the preview window. However, of course, the real-time preview will not be functional yet. Note that we will make another addition to the File Type Component Builder later, when we reference the (yet-to-be-created) preview control (see chapter [Adding a Preview UI Control](adding_a_preview_ui_control.md)) +This object references the preview name that you defined in the resources file. After you add the real-time preview set, Var:ProductName lists the preview name in the Preview window combo box. The real-time preview still does not work yet, because the preview control has not been added. You will add that reference later. See [Adding a Preview UI Control](adding_a_preview_ui_control.md). # [C#](#tab/tabid-1) ```cs @@ -37,14 +39,9 @@ if (targetControlPreviewType2 != null) } previewFactory.GetPreviewSets(null).Add(internalRealPreviewSet); ``` -*** - -See Also --- - - +## See also -[Adding a Preview Controller](adding_a_preview_controller.md) +- [Adding a Preview Controller](adding_a_preview_controller.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/enhance_plugin_introduction.md b/apiconcepts/filetypesupport/enhance_plugin_introduction.md index c9b98664f6..05bdbe16cb 100644 --- a/apiconcepts/filetypesupport/enhance_plugin_introduction.md +++ b/apiconcepts/filetypesupport/enhance_plugin_introduction.md @@ -1,16 +1,14 @@ -Introduction -=== +# Introduction -Apart from the classes that you implemented in the previous chapters there are other (optional) components that you may add to your file type plug-in in order to extend its functionality. +In addition to the classes from the previous chapters, you can add optional components to extend your file type plug-in. -Implementing Extended Functionality --- +## Implement extended functionality -The minimum requirement for a file type plug-in component is, of course, to read a file and convert it into a bilingual format (extraction) and to convert the target content back to the native file format (generation). +At a minimum, a file type plug-in must read a file, convert it to a bilingual format for extraction, and convert the target content back to the native file format for generation. -There are a number of features to add to your file type plug-in to either make life easier for translators by allowing them to quickly insert frequently used elements (QuickInsert). However, most importantly, your file type plug-in may require certain settings to meet the requirements of particular native file formats. +You can also add features that make translation easier. For example, QuickInsert helps translators insert frequently used elements more quickly. Your plug-in may also need settings that support specific native file formats. -For example, Microsoft PowerPoint documents can contain speaker notes, which may be translatable or not. This is why the standard PPT filter that is delivered with Var:ProductName implements a setting that allows you to decide on a case-by-case basis whether to expose speaker note content for translation or not. In the following chapters you will learn how to add such extended functionality to your file type plug-in. +For example, Microsoft PowerPoint documents can contain speaker notes that may or may not require translation. For that reason, the standard PPT filter in Var:ProductName includes a setting that lets you decide whether to expose speaker note content for translation. The following chapters explain how to add this type of extended functionality to your file type plug-in. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/enhancing_the_file_parser_to_process_the_settings.md b/apiconcepts/filetypesupport/enhancing_the_file_parser_to_process_the_settings.md index 6d8ff0eab7..0fcd5a3a2f 100644 --- a/apiconcepts/filetypesupport/enhancing_the_file_parser_to_process_the_settings.md +++ b/apiconcepts/filetypesupport/enhancing_the_file_parser_to_process_the_settings.md @@ -1,20 +1,18 @@ -Enhancing the File Parser to Process the Settings -=== +# Enhancing the File Parser to Process the Settings -Now that you have implemented the user interface for configuring the file type plug-in settings as well as the functionality to load and save these settings, you need to extend your file parser class to make it 'aware' of the settings, so that they can be taken into consideration when processing a given file. +After implementing the user interface for configuring the file type plug-in settings and the functionality to load and save settings, extend your file parser class to be settings-aware so it considers settings when processing files. -Add and Initialize the Settings Property --- +## Add and Initialize the Settings Property -First, you need to make sure that your parser class also uses the following, additional namespaces: +Ensure your parser class uses the following additional namespaces: -* **Sdl.FileTypeSupport.Framework.IntegrationApi** -* **Sdl.Core.Settings** -* **Sdl.FileTypeSupport.Framework.Core.Settings** +- **Sdl.FileTypeSupport.Framework.IntegrationApi** +- **Sdl.Core.Settings** +- **Sdl.FileTypeSupport.Framework.Core.Settings** -Then your parser class needs to implement the ```ISettingsAware``` interface, which makes it 'aware' of the plug-in settings and provides the method that allows it to initialize the settings. +Implement the `ISettingsAware` interface in your parser class. This interface makes the parser settings-aware and provides the method to initialize the settings. -In the next step, add the following boolean property to your parser class: +Add the following boolean property to your parser class: # [C#](#tab/tabid-1) ```cs @@ -24,11 +22,10 @@ public bool LockPrdCodes set; } ``` -*** -The property corresponds to the setting that has been retrieved through the settings UI. +This property corresponds to the setting retrieved through the settings UI. -Then, use the ```InitializeSettings``` method of the interface to initialize the plug-in setting. Within this method, we call on the UserSettings class and apply the ```PopulateFromSettingsBundle``` method to retrieve the current plug-in configuration and then set the ```LockPrdCodes``` of the main verifier component accordingly. +Use the `InitializeSettings` method to initialize the plug-in setting. Call the `UserSettings` class and apply `PopulateFromSettingsBundle` to retrieve the current plug-in configuration. Set the `LockPrdCodes` property accordingly: # [C#](#tab/tabid-2) ```cs @@ -39,9 +36,8 @@ public void InitializeSettings(Sdl.Core.Settings.ISettingsBundle settingsBundle, LockPrdCodes = _userSettings.LockPrdCodes; } ``` -*** -Modify the ```ProcessLine()``` helper function so that it triggers ```WriteLockedContent()``` only if the current line starts with the *Prd-Code* string and if ```LockPrdCodes``` equals True. +Modify the `ProcessLine()` helper function to call `WriteLockedContent()` only when the current line starts with the *Prd-Code* string and `LockPrdCodes` equals True: # [C#](#tab/tabid-3) ```cs @@ -56,34 +52,25 @@ private void ProcessLine(string sLine) WriteStructureTag(sLine); WriteContext(sLine); } - else if (sLine.StartsWith("Prd-Code") && LockPrdCodes==true) + else if (sLine.StartsWith("Prd-Code") && LockPrdCodes == true) { WriteLockedContent(sLine); - - } + } else { WriteText(ProcessFormatting(sLine)); } } ``` -*** - -After making these changes your file parser should now respond to settings changes made at runtime. - -See Also --- - - - -[Creating a New Assembly for the Settings UI](creating_a_new_assembly_for_the_settings_ui.md) -[Implementing the Settings UI](implementing_the_settings_ui.md) +Your file parser now responds to settings changes made at runtime. -[Implementing the UI Controller Class](implementing_the_ui_controller_class.md) +## See Also -[Loading and Saving the Settings](loading_and_saving_settings.md) +- [Creating a New Assembly for the Settings UI](creating_a_new_assembly_for_the_settings_ui.md) +- [Implementing the Settings UI](implementing_the_settings_ui.md) +- [Implementing the UI Controller Class](implementing_the_ui_controller_class.md) +- [Loading and Saving the Settings](loading_and_saving_settings.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/enhancing_the_preview_file_writer.md b/apiconcepts/filetypesupport/enhancing_the_preview_file_writer.md index ba0ec36279..512aa16dad 100644 --- a/apiconcepts/filetypesupport/enhancing_the_preview_file_writer.md +++ b/apiconcepts/filetypesupport/enhancing_the_preview_file_writer.md @@ -1,17 +1,14 @@ -Enhancing the Preview File Writer -=== +# Enhancing the preview file writer -In this chapter you will learn how to enhance the preview writer component to support the dynamic functionality of the real-time preview. +This article shows how to enhance the preview writer to support the dynamic behavior of the real-time preview. -Why you Should Enhance the Preview Writer --- +## Why you should enhance the preview writer -For the static preview writer it was sufficient to output very simple HTML code (see [Implementing the Preview Writer](implementing_the_preview_writer.md)). However, to implement a dynamic real-time preview, which allows users to click segments and jump to the corresponding row in the side-by-side editor, the preview needs to implement active elements through the addition of CSS and JavaScript. +The static preview writer only needs to generate simple HTML. See [Implementing the Preview Writer](implementing_the_preview_writer.md). A dynamic real-time preview needs more support. Users can click segments and jump to the corresponding row in the side-by-side editor, so the preview must include active elements through CSS and JavaScript. -Enhance the HTML Header --- +## Enhance the HTML header -The currently selected (i.e. active) segment in the real-time preview should be highlighted, e.g. with a silver background, while unselected segments retain a white background. In our case, this can be best implemented through CSS stylesheets. Therefore, the header of the preview file will contain the following styles, which are applied to the currently selected segment (```activesegment```) and to the unselected segments (```normal```). +The real-time preview should highlight the currently selected segment, for example with a silver background. Unselected segments should keep a white background. In this sample, CSS handles that styling. Add the following styles to the preview file header. The `activesegment` style formats the selected segment, and the `normal` style formats unselected segments. # [HTML](#tab/tabid-1) ```html @@ -24,11 +21,10 @@ The currently selected (i.e. active) segment in the real-time preview should be .normal {color:black; background-color:white; cursor:hand;} ``` -*** -Moreover, we will use two JavaScript functions to apply the ```activesegment``` or the normal styles. These JavaScript functions can later be called from the Web browser preview control, which we will implement in one of the following chapters (see [Adding a Preview UI Control](adding_a_preview_ui_control.md)). +Add two JavaScript functions to switch between the `activesegment` and `normal` styles. The web browser preview control can call these functions later. See [Adding a Preview UI Control](adding_a_preview_ui_control.md). -# [C#](#tab/tabid-2) +# [HTML](#tab/tabid-2) ```html ``` -*** -First, it is best to add a separate helper function that generates the HTML header as shown below: +Next, add a helper function that generates the HTML header: # [C#](#tab/tabid-3) ```cs @@ -89,9 +84,8 @@ private string GetHTMLStart() return header; } ``` -*** -Modify the [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) member as shown below to call the above helper function, which generates the HTML header: +Update the [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) member to call this helper function: # [C#](#tab/tabid-4) ```cs @@ -102,23 +96,19 @@ public void StartOfInput() _preview.WriteLine(GetHTMLStart()); } ``` -*** -Enhance the Segment Output to Allow for Navigation --- +## Enhance the segment output to allow navigation -To determine a particular segment to be highlighted in the real-time preview when the user selects it in the side-by-side editor (or vice versa), you require two parameters: the paragraph unit id and the segment id. +To highlight a segment in the real-time preview when the user selects it in the side-by-side editor, you need two parameters: the paragraph unit ID and the segment ID. -First, we add the paragraph unit as a string member to the writer class: +First, add the paragraph unit as a string member to the writer class: # [C#](#tab/tabid-5) ```cs string _paragraphUnitId = String.Empty; ``` -*** - -Then we enhance the [ParagraphUnitStart](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_ParagraphUnitStart_Sdl_FileTypeSupport_Framework_NativeApi_IParagraphUnitProperties_) method to set the value of ```_paragraphUnitId``` to the id of the currently selected paragraph unit. +Next, update the [ParagraphUnitStart](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_ParagraphUnitStart_Sdl_FileTypeSupport_Framework_NativeApi_IParagraphUnitProperties_) method so that `_paragraphUnitId` stores the ID of the current paragraph unit. # [C#](#tab/tabid-6) ```cs @@ -128,10 +118,10 @@ public override void ParagraphUnitStart(IParagraphUnitProperties properties) { _preview.WriteLine("
"); _paragraphUnitId = properties.ParagraphUnitId.Id; +} ``` -*** -Next, we make the segments in the real-time preview 'clickable' by outputting the following HTML through the [SegmentStart](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_SegmentStart_Sdl_FileTypeSupport_Framework_NativeApi_ISegmentPairProperties_) method: +Then make the segments in the real-time preview clickable by writing the following HTML through the [SegmentStart](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_SegmentStart_Sdl_FileTypeSupport_Framework_NativeApi_ISegmentPairProperties_) method: # [C#](#tab/tabid-7) ```cs @@ -141,10 +131,10 @@ public override void SegmentStart(ISegmentPairProperties properties) _preview.Write(""); } ``` -*** -The **SPAN** tag now includes an onClick event handler, which passes the segment id and the paragraph unit id. -Below you see an example of the HTML code the enhanced preview writer will generate for a paragraph unit that contains two segments: +The **SPAN** tag now includes an `onClick` event handler that passes the segment ID and the paragraph unit ID. + +The following example shows the HTML generated for a paragraph unit that contains two segments: # [HTML](#tab/tabid-8) ```html @@ -157,12 +147,10 @@ Opens a dialog box on start-up.
``` -**** -Putting it All Together --- +## Put it all together -Your enhanced preview writer class should now look as shown below. Note that the same preview writer can be used both for the internal static and the real-time preview. There is no harm in having the styles and JavaScript functions in the static preview, they will just never be called. +The enhanced preview writer class should now look like this. You can use the same preview writer for both the internal static preview and the real-time preview. The static preview can include the styles and JavaScript functions even though it never calls them. # [C#](#tab/tabid-9) ```cs @@ -183,25 +171,19 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview // not used in this implementation } - #region "start output" // start the preview output public void StartOfInput() { _preview = new StreamWriter(OutputProperties.OutputFilePath); _preview.WriteLine(GetHTMLStart()); } - #endregion - #region "text" // output the translatable strings public override void Text(ITextProperties textInfo) { _preview.Write(textInfo.Text); } - #endregion - #region "para" - #region "para start" // each paragraph unit should appear in a new line // therefore use a DIV element public override void ParagraphUnitStart(IParagraphUnitProperties properties) @@ -209,23 +191,19 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview _preview.WriteLine("
"); _paragraphUnitId = properties.ParagraphUnitId.Id; } - #endregion public override void ParagraphUnitEnd() { _preview.Write("
"); } - #endregion - #region "segment" // enclose each segment in a SPAN tag pair public override void SegmentStart(ISegmentPairProperties properties) { _preview.Write(""); } - #endregion public override void SegmentEnd() { @@ -233,7 +211,6 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview } - #region "inline tags" // output any inline tags, // which will also apply the corresponding character formatting public override void InlineStartTag(IStartTagProperties tagInfo) @@ -245,20 +222,16 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview { _preview.Write(tagInfo.TagContent); } - #endregion - #region "end output" // end the preview output public void EndOfInput() { _preview.WriteLine(""); _preview.Close(); } - #endregion - #region "html start" // write the HTML header, which contains CSS styles // and JavaScript functions, which can be called from the // preview viewer control @@ -299,11 +272,14 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.Preview header += "\n"; return header; } - #endregion } } ``` -*** + +## See also + +- [Implementing the Preview Writer](implementing_the_preview_writer.md) +- [Adding a Preview UI Control](adding_a_preview_ui_control.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/extending_existing_file_type_component_builder.md b/apiconcepts/filetypesupport/extending_existing_file_type_component_builder.md index f633f99e76..133165fd56 100644 --- a/apiconcepts/filetypesupport/extending_existing_file_type_component_builder.md +++ b/apiconcepts/filetypesupport/extending_existing_file_type_component_builder.md @@ -1,24 +1,21 @@ -Extending existing File Type Component Builder -=== +# Extending Existing File Type Component Builder ->[!NOTE] -> ->This functionality is only available in Studio 2011 SP3. +Extend the existing XML File Type Component Builder so your native verifier is used when processing XML files. -This chapter provides basic information on extending existing XML File Type Component Builder so your native verifier will be used when processing XML files. +## Overview -Extending an existing XML File Type Component Builder -As XML is one of the standard formats supported by Var:ProductName, the corresponding File Type Component Builder already exists. The XML File Type Component Builder will be used to create an extension of the XML File Type Component Builder that uses your native verifier. +XML is one of the standard formats supported by Var:ProductName, so the corresponding File Type Component Builder already exists. Use this XML File Type Component Builder to create an extension that includes your native verifier. -A File Type Component Builder is defined by a filter component builder that implements [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). A filter component builder knows how to create parsers, writers, and so on for the corresponding file type. XML File Type Component Builder has a filter component builder. +A File Type Component Builder is defined by a filter component builder that implements [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). The filter component builder knows how to create parsers, writers, and other components for the file type. The XML File Type Component Builder has its own filter component builder. -The XML File Type Component Builder can be inherited from indirectly by implementing the [IFileTypeComponentBuilderAdapter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilderAdapter.yml) interface. To create an extension for the XML File Type Component Builder you need to add the ```FileTypeComponentBuilderExtension``` attribute to your extension component builder class.You must set the ```OriginalFileType``` property of the attribute to ```XML: Any v 1.2.0.0```. You can now access the original XML component builder methods through the ```Original``` property as shown in the code example at the end of this page. +To extend the XML File Type Component Builder indirectly, implement the [IFileTypeComponentBuilderAdapter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilderAdapter.yml) interface. Add the `FileTypeComponentBuilderExtension` attribute to your extension component builder class. Set the `OriginalFileType` property to `XML: Any v 1.2.0.0`. You can access the original XML component builder methods through the `Original` property. ->[!NOTE] -> ->In Var:ProductName all the file type plug-in components are designed in a way that you can extend all the functionality. +> [!NOTE] +> In Var:ProductName, all file type plug-in components are designed to be extensible, so you can extend all functionality. -Every extension filter component builder needs to have a [FileTypeComponentBuilderExtensionAttribute](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.FileTypeComponentBuilderExtensionAttribute.yml) that describes the file type component builder. +## Create the Extension + +Every extension filter component builder requires a [FileTypeComponentBuilderExtensionAttribute](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.FileTypeComponentBuilderExtensionAttribute.yml) that describes the file type component builder: # [C#](#tab/tabid-1) ```cs @@ -28,10 +25,8 @@ Every extension filter component builder needs to have a [FileTypeComponentBuild Description = "XML_FilterComponentBuilderExtension_Verifier_Description", OriginalFileType = "XML: Any v 1.2.0.0")] ``` -*** - -"XML_FilterComponentBuilderExtension_Verifier_Name" and "XML_FilterComponentBuilderExtension_Verifier_Description" refers to entries in the **PlugInResources.resx** file. +The `XML_FilterComponentBuilderExtension_Verifier_Name` and `XML_FilterComponentBuilderExtension_Verifier_Description` values refer to entries in the **PlugInResources.resx** file: # [Xml](#tab/tabid-1) ```xml @@ -42,26 +37,26 @@ Every extension filter component builder needs to have a [FileTypeComponentBuild Length Check XML Filter Component Builder ``` -*** -At this point, we have a new file type definition that is identical to the standard XML File Type Component Builder. This new file type definition needs to be changed so it includes the new native verifier. This can be accomplished simply by calling the original **BuildVerifierCollection** and adding the new verifier to this collection. +## Modify the File Type Definition + +At this point, you have a new file type definition identical to the standard XML File Type Component Builder. Modify it to include the new native verifier by calling the original `BuildVerifierCollection` and adding the new verifier to the collection: # [C#](#tab/tabid-2) ```cs -public IVerifierCollection BuildVerifierCollection(string name) +public IVerifierCollection BuildVerifierCollection(string name) { var verifierCollection = Original.BuildVerifierCollection(name); verifierCollection.NativeVerifiers.Add(new XMLCheckerMain()); return verifierCollection; } ``` -*** -This new file type definition also needs to be changed so it includes the new native verifier settings page. This is accomplished by calling the original **BuildFileTypeInformation** and adding the settings page to **WinFormSettingsPageIds**. +Modify the file type definition to include the native verifier settings page. Call the original `BuildFileTypeInformation` and add the settings page to `WinFormSettingsPageIds`: # [C#](#tab/tabid-3) ```cs -public IFileTypeInformation BuildFileTypeInformation(string name) +public IFileTypeInformation BuildFileTypeInformation(string name) { var fileTypeInformation = Original.BuildFileTypeInformation(name); // add "XMLVerifier_Settings" to existing WinFormSettingsPageIds @@ -71,9 +66,10 @@ public IFileTypeInformation BuildFileTypeInformation(string name) return fileTypeInformation; } ``` -*** -Here is the complete code for creating a new file type definition based upon the XML file type definition using the new native verifier. +## Complete Implementation + +Here's the complete code for creating a new file type definition based on the XML file type definition with the new native verifier: # [C#](#tab/tabid-4) ```cs @@ -90,7 +86,7 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker OriginalFileType = "XML: Any v 1.2.0.0")] public class VerifierFilterComponentBuilder : IFileTypeComponentBuilderAdapter { - public IFileTypeInformation BuildFileTypeInformation(string name) + public IFileTypeInformation BuildFileTypeInformation(string name) { var fileTypeInformation = Original.BuildFileTypeInformation(name); // add "XMLVerifier_Settings" to existing WinFormSettingsPageIds @@ -100,7 +96,7 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker return fileTypeInformation; } - public IVerifierCollection BuildVerifierCollection(string name) + public IVerifierCollection BuildVerifierCollection(string name) { var verifierCollection = Original.BuildVerifierCollection(name); verifierCollection.NativeVerifiers.Add(new XMLCheckerMain()); @@ -165,19 +161,12 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker } } ``` -*** - -See Also --- - - - -[Implement the User Interface](implement_the_user_interface_native.md) -[Implement the UI Controller Class](implement_the_ui_controller_class_native.md) +## See Also -[Implement the Verification Logic](implement_the_verification_logic_native.md) +- [Implement the User Interface](implement_the_user_interface_native.md) +- [Implement the UI Controller Class](implement_the_ui_controller_class_native.md) +- [Implement the Verification Logic](implement_the_verification_logic_native.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/extending_the_configuration_options.md b/apiconcepts/filetypesupport/extending_the_configuration_options.md index b9cc892dcd..4a8969584c 100644 --- a/apiconcepts/filetypesupport/extending_the_configuration_options.md +++ b/apiconcepts/filetypesupport/extending_the_configuration_options.md @@ -1,27 +1,22 @@ -Extending the Configuration Options -=== +# Extending the Configuration Options -This chapter provides an example of how to enhance your file type plug-in with another configuration option. +Enhance your file type plug-in with another configuration option. -Add Another File Type Plug-in Option --- +## Add Another File Type Plug-in Option -Let us assume that the product code prefix may vary from file to file. In this case it makes sense to implement the product code string as an option that can be configured at runtime rather than hard-coding it in the application. This requires some additions to the filter settings, the control UI, and the file parser component. +Consider that the product code prefix may vary from file to file. Rather than hard-coding the prefix, implement it as a runtime configuration option. This requires additions to the filter settings, the control UI, and the file parser component. -Extend the File Type Settings --- +## Extend the File Type Settings -Before we can add the new option to the UI Control we first need to add it to the filter settings. The new setting should follow the same pattern as other settings we have added to the settings class - we will need to add a settings key, a default value, and an accessor property for the setting. We also need to update the ```ResetToDefaults```, ```PopulateFromSettingsBundle``` and ```SaveToSettingsBundle``` methods to handle the new setting. See **Putting It All Together** for an example of how to do this. +Before adding the new option to the UI control, add it to the filter settings. The new setting should follow the same pattern as existing settings—add a settings key, a default value, and an accessor property. Update the `ResetToDefaults`, `PopulateFromSettingsBundle`, and `SaveToSettingsBundle` methods to handle the new setting. See **Putting It All Together** for an example. -Extend the UI Control --- +## Extend the UI Control -Extend the file type plug-in settings UI by adding a new text field called e.g. ```txt_PrdCodePrefix```. +Extend the file type plug-in settings UI by adding a new text field called `txt_PrdCodePrefix`: ![SimpleFilterExtendedUI](images/SimpleFilterExtendedUI.jpg) - -Add a helper function that enables or disables the new text field depending on whether the ```cb_LockPrdCodes``` check box is checked or not: +Add a helper function that enables or disables the text field depending on whether the `cb_LockPrdCodes` check box is checked: # [C#](#tab/tabid-1) ```cs @@ -30,7 +25,6 @@ private void txt_PrdCodePrefix_TextChanged(object sender, EventArgs e) _userSettings.PrdCodesPrefix = txt_PrdCodePrefix.Text; } ``` -*** # [C#](#tab/tabid-2) ```cs @@ -40,13 +34,10 @@ public void UpdateControl() txt_PrdCodePrefix.Text = _userSettings.PrdCodesPrefix; } ``` -*** - -Modify the File Parser --- +## Modify the File Parser -Last, you need to modify the file parser component, so that it uses the configurable product code prefix property rather than the hard-coded string. First, add a new global property to the file parser class: +Modify the file parser component to use the configurable product code prefix property instead of a hard-coded string. First, add a new global property to the file parser class: # [C#](#tab/tabid-3) ```cs @@ -56,9 +47,8 @@ public string PrdCodesPrefix set; } ``` -*** -In the ```InitializeSettings``` method you need to read this property from the user settings to initialize the file parser class. Here is the complete method with ```PrdCodesPrefix``` initialized from the user settings. +In the `InitializeSettings` method, read this property from the user settings to initialize the file parser class: # [C#](#tab/tabid-4) ```cs @@ -70,15 +60,13 @@ public void InitializeSettings(Sdl.Core.Settings.ISettingsBundle settingsBundle, PrdCodesPrefix = userSettings.PrdCodesPrefix; } ``` -*** -In the ProcessLine() function you then need to change the ```else if ```condition from: +In the `ProcessLine()` function, change the `else if` condition from: # [C#](#tab/tabid-5) ```cs - else if (sLine.StartsWith("Prd-Code") && LockPrdCodes==true) +else if (sLine.StartsWith("Prd-Code") && LockPrdCodes==true) ``` -*** to: @@ -86,14 +74,12 @@ to: ```cs else if (sLine.StartsWith(PrdCodePrefix) && LockPrdCodes==true) ``` -**** -After rebuilding your project, the file type plug-in should implement the second configuration option and apply it during parsing. +After rebuilding your project, the file type plug-in implements the second configuration option and applies it during parsing. -Putting It All Together --- +## Putting It All Together -Your extended ```UserSettings``` class should now look as shown below: +Your extended `UserSettings` class should now look as follows: # [C#](#tab/tabid-7) ```cs @@ -108,7 +94,6 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText /// public class UserSettingsExtended : FileTypeSettingsBase { - #region "Properties" private const string SettingsLockPrdCodes = "LockPrdCodes"; private const string SettingsPrdCodesPrefix = "PrdCodesPrefix"; @@ -137,26 +122,21 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText OnPropertyChanged("PrdCodesPrefix"); } } - #endregion - #region "Constructor" public UserSettingsExtended() { ResetToDefaults(); } - #endregion /// /// Define the default value, which is Enabled, as the product code strings should /// not be exposed to translation by default. /// - #region "ResetToDefaults" public override sealed void ResetToDefaults() { LockPrdCodes = DefaultLockPrdCodes; PrdCodesPrefix = DefaultPrdCodePrefix; } - #endregion /// /// This method is used to load the setting from the settings bundle, @@ -164,14 +144,12 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText /// /// /// - #region "PopulateFromSettingsBundle" public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, string filterDefinitionId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(filterDefinitionId); LockPrdCodes = GetSettingFromSettingsGroup(settingsGroup, SettingsLockPrdCodes, DefaultLockPrdCodes); PrdCodesPrefix = GetSettingFromSettingsGroup(settingsGroup, SettingsPrdCodesPrefix, DefaultPrdCodePrefix); } - #endregion /// /// This method is used to store the settings as configured in the plug-in UI @@ -180,20 +158,17 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText /// /// /// - #region "SaveToSettingsBundle" public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string filterDefinitionId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(filterDefinitionId); UpdateSettingInSettingsGroup(settingsGroup, SettingsLockPrdCodes, LockPrdCodes, DefaultLockPrdCodes); UpdateSettingInSettingsGroup(settingsGroup, SettingsPrdCodesPrefix, PrdCodesPrefix, DefaultPrdCodePrefix); } - #endregion } } ``` -*** -Your extended `SettingsUI` class should now look as shown below: +Your extended `SettingsUI` class should now look as follows: # [C#](#tab/tabid-8) ```cs @@ -212,50 +187,40 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.WinUI /// /// Implements the user interface for the file type definition. /// - #region "ClassDeclaration" public partial class SettingsUIExtended : UserControl, IFileTypeSettingsAware - #endregion { /// /// Create a settings object based on the UserSettings class. /// - #region "SettingsObject" private UserSettingsExtended _userSettings; - #endregion /// - /// Initalize the user interface control by setting it to the + /// Initialize the user interface control by setting it to the /// setting value stored in the settings bundle. /// - #region "Initialize" public SettingsUIExtended() { InitializeComponent(); } - #endregion - /// /// Reset the user interface control to its default value, which is /// checked, i.e. the product lock option should be enabled /// by default. /// - #region "UpdateControl" public void UpdateControl() { cb_LockPrdCodes.Checked = _userSettings.LockPrdCodes; txt_PrdCodePrefix.Text = _userSettings.PrdCodesPrefix; } - #endregion /// - /// Save the settings based on the value of the the check box. + /// Save the settings based on the value of the check box. /// The setting is saved through the UserSettings class, which /// handles the plug-in settings bundle. /// /// /// - #region "SaveSetting" private void cb_LockPrdCodes_CheckedChanged(object sender, EventArgs e) { _userSettings.LockPrdCodes = cb_LockPrdCodes.Checked; @@ -265,20 +230,16 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.WinUI else txt_PrdCodePrefix.Enabled = false; } - #endregion - #region "SaveTextBox" private void txt_PrdCodePrefix_TextChanged(object sender, EventArgs e) { _userSettings.PrdCodesPrefix = txt_PrdCodePrefix.Text; } - #endregion /// - /// Implementation of IFileTypeSettingsAware allowing the Filter Framework + /// Implementation of IFileTypeSettingsAware allowing the Filter Framework /// to pass through the user settings so that we can initialize the UI. /// - #region "ApplySettings" public UserSettingsExtended Settings { get @@ -291,11 +252,9 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.WinUI UpdateControl(); } } - #endregion } } ``` -**** ->[!NOTE] -> + +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/extending_the_filter_component_builder.md b/apiconcepts/filetypesupport/extending_the_filter_component_builder.md index de11575665..9b51f30391 100644 --- a/apiconcepts/filetypesupport/extending_the_filter_component_builder.md +++ b/apiconcepts/filetypesupport/extending_the_filter_component_builder.md @@ -1,17 +1,14 @@ -Extending the Filter Component Builder -=== -This section shows how to extend an existing file type plug-in +# Extending the Filter Component Builder ->[!NOTE] -> ->Please note that this functionality is only available in Studio 2011 SP3. +This page shows how to extend an existing file type plug-in. -Existing file type plug-in can be extended by implementing the ```IFileTypeComponentBuilderAdapter``` interface and applying the ```FileTypeComponentBuilderExtensionAttribute``` attribute to the component builder class. Using this technique it is easy to add new [Pre and Post Tweakers](native_file_tweakers.md), add new Native and Bilingual Content Processors to the [Parser](the_file_parser.md) and to the [Writer]the_file_writer.md) and add new Verifiers (Native or Bilingual). It also allows to redefine the file type plug-ins [Sniffer](the_file_sniffer.md) and the [IFileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeInformation.yml) associated to the file type plug-in. For more advanced users it is also possible to define a new [File Preview mechanism](the_filter_preview.md) to existing file type plug-in. +You can extend an existing file type plug-in by implementing the `IFileTypeComponentBuilderAdapter` interface and applying the `FileTypeComponentBuilderExtensionAttribute` attribute to the component builder class. This approach lets you add [pre- and post-tweakers](native_file_tweakers.md), add native and bilingual content processors to the [parser](the_file_parser.md) and [writer](the_file_writer.md), and add native or bilingual verifiers. It also lets you redefine the plug-in [sniffer](the_file_sniffer.md), update the associated [IFileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeInformation.yml), or define a new [file preview mechanism](the_filter_preview.md) for an existing file type plug-in. -How to do it --- +## How to extend a builder -The Filter extension implementation consists of a class that implements the ```IFileTypeComponentBuilderAdapter``` interface. The original File Type Component Builder can be accessed by the ```Original``` property. For example to add a new [IFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFilePreTweaker.yml) to the existing SimpleText Filter provided with the examples of this SDK it is enough to implement the [BuildFileExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.DynamicFilterComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_DynamicFilterComponentBuilder_BuildFileExtractor_System_String_) method, call the original method and add the new tweaker to the [INativeExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeExtractor.yml) using [AddFileTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileExtractor.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileExtractor_AddFileTweaker_Sdl_FileTypeSupport_Framework_NativeApi_IFilePreTweaker_) method. The following code shows how to do this: +A filter extension is implemented as a class that implements `IFileTypeComponentBuilderAdapter`. You can access the original File Type Component Builder through the `Original` property. + +For example, to add a new [IFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFilePreTweaker.yml) to the existing SimpleText filter from the SDK samples, implement the [BuildFileExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.DynamicFilterComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_DynamicFilterComponentBuilder_BuildFileExtractor_System_String_) method, call the original method, and add the tweaker to the [INativeExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeExtractor.yml) by using [AddFileTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileExtractor.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileExtractor_AddFileTweaker_Sdl_FileTypeSupport_Framework_NativeApi_IFilePreTweaker_). The following example shows this pattern: # [C#](#tab/tabid-1) ```cs @@ -35,13 +32,14 @@ public IFileExtractor BuildFileExtractor(string name) return extractor; } ``` -*** -where ```SimpleTextExtensionPreTweaker``` is the class that implements the new Tweaker that is being added. +In this example, `SimpleTextExtensionPreTweaker` implements the new tweaker. + +The filter framework does not support extending an extension or extending a filter template. Those approaches can produce unexpected results. -Note that extending an extension and extending a filter template are not supported by the filter framework and can have unexpected results. +The next example shows part of the `SimpleTextExtension` sample project. The class uses the `FileTypeComponentBuilderExtensionAttribute` attribute to enable the plug-in mechanism. Set the `OriginalFileType` property to the `FileTypeId` of the file type that you want to extend. For more information, see [Build the File Type Plug-in](build_the_file_type_plug_in.md). -The next code shows part of the example (SimpleTextExtension) included with the sample projects. Note that the class has an attribute called ```FileTypeComponentBuilderExtensionAttribute``` to enable the plug-in mechanism. The property ```OriginalFileType``` must be set to match the FileTypeId of the FileType you wish to extend. Please refer to the [Build the File Type Plug-in](build_the_file_type_plug_in.md) topic for more information. +## Full example # [C#](#tab/tabid-2) ```cs @@ -79,7 +77,6 @@ namespace Sdk.FileTypeSupport.Samples.SimpleTextExtension return Original.BuildFileSniffer(name); } - #region BuildFileExtractor public IFileExtractor BuildFileExtractor(string name) { // remember to call the original component builder method @@ -99,7 +96,6 @@ namespace Sdk.FileTypeSupport.Samples.SimpleTextExtension return extractor; } - #endregion public IFileGenerator BuildFileGenerator(string name) { @@ -173,9 +169,8 @@ namespace Sdk.FileTypeSupport.Samples.SimpleTextExtension } } ``` -*** -Note that if the ```FileTypeDefinitionId``` is changed in the ```BuildFileTypeInformation``` section, then the extension will appear as a new filter in the Studio file type options dialog. Otherwise it will simply override the original one (i.e. no new filter will appear in U.I.) +If you change `FileTypeDefinitionId` in `BuildFileTypeInformation`, the extension appears as a new filter in the Studio file type options dialog. Otherwise, it overrides the original filter and no new filter appears in the UI. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/extracting_comments.md b/apiconcepts/filetypesupport/extracting_comments.md index 5cb4746731..fa4f0741cd 100644 --- a/apiconcepts/filetypesupport/extracting_comments.md +++ b/apiconcepts/filetypesupport/extracting_comments.md @@ -1,23 +1,19 @@ -Extracting Comments -=== +# Extracting Comments -In this chapter you will learn how to extract comments from a given BIL file and add them to the intermediary (SDLXliff) document. +Extract comments from a given BIL file and add them to the intermediary (SDLXliff) document. -About Comments --- +## About Comments -A unit in a BIL file can contain one or more comments, e.g.: +A unit in a BIL file can contain one or more comments, for example: # [Xml](#tab/tabid-1) ```xml This segment was translated using web translator. ``` -**** -Extend the Helper Function for Creating Paragraph Units --- +## Extend the Helper Function for Creating Paragraph Units -First, add the following to the ```CreateParagraphUnit()``` helper function: +Add the following to the `CreateParagraphUnit()` helper function: # [C#](#tab/tabid-2) ```cs @@ -27,10 +23,10 @@ if(xmlUnit.SelectSingleNode("comment")!=null) paragraphUnit.Properties.Comments = CreateComment(xmlUnit.SelectSingleNode("comment").InnerText); } ``` -*** -This condition determines whether a ```comment``` element exists in the unit and then passes the comment text to a separate helper function. -The complete ```CreateParagraphUnit()``` helper function looks as shown below: +This condition checks whether a `comment` element exists in the unit and passes the comment text to a separate helper function. + +The complete `CreateParagraphUnit()` helper function looks as follows: # [C#](#tab/tabid-3) ```cs @@ -40,7 +36,6 @@ private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) // create paragraph unit object IParagraphUnit paragraphUnit = ItemFactory.CreateParagraphUnit(LockTypeFlags.Unlocked); - // create segment pair object ISegmentPairProperties segmentPairProperties = ItemFactory.CreateSegmentPairProperties(); // assign the appropriate confirmation level to the segment pair @@ -57,36 +52,35 @@ private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) paragraphUnit.Target.Add(trgSegment); } - #region "context" // create paragraph unit context string id = xmlUnit.SelectSingleNode("./@id").InnerText; if(xmlUnit.SelectSingleNode("type/@spec")!=null) { string spec = xmlUnit.SelectSingleNode("type/@spec").InnerText; - paragraphUnit.Properties.Contexts=CreateContext(spec, id); - } else { + } + else + { paragraphUnit.Properties.Contexts = CreateContext("Paragraph", id); } - #endregion - #region "comments" // extract comment (if applicable) if(xmlUnit.SelectSingleNode("comment")!=null) { paragraphUnit.Properties.Comments = CreateComment(xmlUnit.SelectSingleNode("comment").InnerText); } - #endregion return paragraphUnit; } ``` -*** -Add a Helper Function for Generating the Comments --- +## Add a Helper Function for Generating Comments + +The following helper function generates comments in the intermediary (SDLXliff) file. When generating a comment through the properties factory, provide these parameters: -Below you see the helper function that actually generates the comments in the intermediary (SDLXliff) file. When generating a comment through the properties factory you need to provide the following parameters: the comment text, the user who added the comment (in this case we just use a hard-coded string to keep this example simple), and the [Severity](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IComment.yml#Sdl_FileTypeSupport_Framework_NativeApi_IComment_Severity) level, which we set to ```Medium```. +- Comment text +- User who added the comment (this example uses a hard-coded string for simplicity) +- [Severity](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IComment.yml#Sdl_FileTypeSupport_Framework_NativeApi_IComment_Severity) level (set to `Medium`) # [C#](#tab/tabid-4) ```cs @@ -99,12 +93,10 @@ private ICommentProperties CreateComment(string commentText) return commentProperties; } ``` -*** -In Var:ProductName the comments will be visible in the **Comments** windows. Double-clicking a comment here will lead you directly to the corresponding paragraph unit / segment pair in the editor. +In Var:ProductName, comments appear in the **Comments** window. Double-click a comment to navigate directly to the corresponding paragraph unit or segment pair in the editor. ![ParagraphComments](images/ParagraphComments.jpg) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/file_type_settings.md b/apiconcepts/filetypesupport/file_type_settings.md index 230d689b46..c77d652ea3 100644 --- a/apiconcepts/filetypesupport/file_type_settings.md +++ b/apiconcepts/filetypesupport/file_type_settings.md @@ -1,30 +1,41 @@ -File type settings -===== -Each file format has its particular features, for example, MS PowerPoint files can contain speaker notes, which is a feature specific to this document format. Users may be required to translate speaker notes, or they may have to exclude them from translation, depending on the specific project requirements. A file type plug-in can be equipped with a special settings UI, which allows users to configure settings at runtime. That way, they can determine, for example, whether the file type plug-in should extract speaker notes text from the MS PowerPoint file and make them available for translation/editing in the intermediary format (e.g. SDLXliff) or not. +# File type settings -The more complex a file format is, the more likely it is to require the configuration of settings at runtime. Below are a few examples of file type settings used in Var:ProductName: +Many file formats include features that require configuration at runtime. For example, Microsoft PowerPoint files can contain speaker notes. Depending on the project requirements, users may need to translate those notes or exclude them from translation. A file type plug-in can provide a settings UI so users can decide how the plug-in handles that content in the intermediary format, such as SDLXliff. -* Styles that should be treated as non-translatable in Microsoft Word files -* Extracting the document properties of Microsoft Word files for editing -* Extracting Web addresses found in an Adobe InDesign (INX) file for editing -* Extracting hidden conditional text found in an Adobe InDesign (INX) file for editing -etc. -If your file type plug-in processes a file format that might potentially require users to extract or hide certain content on a case-by-case basis, you need to implement a user interface that exposes the required settings, which can then be configured by the users at runtime. Below you see an example of a settings page for the standard Adobe InDesign (INX) file type plug-in currently used in Var:ProductName. +## When to expose settings - +The more complex a file format becomes, the more likely it needs runtime settings. Common examples in Var:ProductName include: + +- Treating specific Word styles as non-translatable +- Extracting Word document properties for editing +- Extracting web addresses from Adobe InDesign (INX) files for editing +- Extracting hidden conditional text from Adobe InDesign (INX) files for editing + +If your file type plug-in must let users extract or hide content on a case-by-case basis, provide a user interface for those settings. The standard Adobe InDesign (INX) file type plug-in in Var:ProductName uses this approach. + + The settings page for the Adobe InDesign INX file type plug-in -The settings are initially persisted in the default Project Template **Default.sdltpl** file, when edited without a project being open. Under Windows Vista or 7, this is usually located at: *c:\Users\UserName\Documents\SDL Trados Studio\Project Templates\Default.sdltpl* (provided Var:ProductName is installed on your machine). A copy of these settings is made when a new project is created and the settings (for the open project) are then persisted in the project file (*.sdlproj) +## How settings are stored + +When users edit settings without an open project, Var:ProductName stores them in the default project template, **Default.sdltpl**. By default, this file resides here: + +*c:\Users\UserName\Documents\Var:StudioDocumentsFolderName\Project Templates\Default.sdltpl* + +When a user creates a project, Var:ProductName copies the template settings into the project file. By default, the project file resides here: + +*c:\Users\UserName\Documents\Var:StudioDocumentsFolderName\Projects\Project 1\Project 1.sdlproj* + +The project file stores only file type settings that differ from the default template. -For example, when you create a project with the name of, say, **Project 1**, the project file will be located at: *c:\Users\ **UserName**\Documents\SDL Trados Studio\Projects\Project 1\Project 1.sdlproj*, assuming the default location for the project. The non-default settings for all file types will be stored in this project file (i.e. only settings which have been changed for file types are stored). +You can also import or export settings through the UI. -You can also export or import settings from the default template using the UI +## Dependency requirements -There would be problems when a user tries to open an intermediary (SDLXliff) file which was generated by a file type plug-in whose binaries are not available on the machine on which the file is to be translated or edited. It would be possible to open the intermediary file and translate/edit it, however, it would not be possible to generate, for example, the native target file, previews, etc., because the binaries required to perform these functions are not accessible. +If a user opens an intermediary SDLXliff file that a file type plug-in created, the machine must have the plug-in binaries installed. Without those binaries, users can still open and edit the intermediary file, but they cannot generate the native target file or previews. -See Also ----------- -[Implementing the Settings UI](implementing_the_settings_ui.md) +## See also -[Implementing the UI Controller Class](implementing_the_ui_controller_class.md) +- [Implementing the Settings UI](implementing_the_settings_ui.md) +- [Implementing the UI Controller Class](implementing_the_ui_controller_class.md) diff --git a/apiconcepts/filetypesupport/file_type_support_overview.md b/apiconcepts/filetypesupport/file_type_support_overview.md index 3e6a47a52b..18cdeee223 100644 --- a/apiconcepts/filetypesupport/file_type_support_overview.md +++ b/apiconcepts/filetypesupport/file_type_support_overview.md @@ -1,62 +1,61 @@ -The Trados File Type Support Framework 2 API (from now File Type Support Framework), is one of the core parts of Var:ProductName. The File Type Support Framework allows developers to develop file type plug-ins that extract translatable text from various file formats such as MS Word Doc files, HTML, XML, Text etc. The translatable source and (optionally) target text can then be imported and converted into an intermediate file format that is designed to be compatible with the OASIS XLIFF format (with SDL extensions) - [SDLXliff](#sdlxliff). +# File Type Support Framework overview -This data format contains both source and target text and any mark-up data or tags that the file filter has found. These tags can be either paired or placeholder tags, which can be moved deleted or cloned in the translation. They can also be structure tags that represent fixed non-translatable elements in the original file format, which must be preserved. Other applications such as the editor or the translation memory subsystems also use this framework to interact with the given file formats and can read and update these structures as required. +The `Var:ProductName` File Type Support Framework 2 API is a core part of `Var:ProductName`. It lets developers build file type plug-ins that extract translatable text from formats such as Microsoft Word, HTML, XML, and plain text. The framework then converts the extracted source text, and optionally target text, into an intermediate bilingual format that is compatible with OASIS XLIFF and extended by [SDLXliff](#sdlxliff). -The core APIs of the File Type Support Framework consist of the following Var:DotNetVersion assemblies: +This intermediate format stores source and target text together with markup and tags discovered by the file filter. Tags can be paired tags or placeholder tags, which translators can move, delete, or clone when appropriate. The format can also contain structure tags that represent fixed, non-translatable elements from the original file and must remain intact. Other applications, such as the editor and translation memory subsystems, also use this framework to read and update the same structures. + +The core APIs of the File Type Support Framework are provided by the following `Var:DotNetVersion` assemblies: ![Implementation_Diagram__CoreModules](images/Implementation_Diagram__CoreModules.jpg) -Below you find a brief description of what each assembly contains: +The following list summarizes each assembly: + +* [Sdl.FileTypeSupport.Framework](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.yml): Provides the basic data types shared across all modules, such as the `FrameworkException` base class and the `Language` and `Codepage` classes. +* [Sdl.FileTypeSupport.Framework.NativeApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.yml): Provides the interfaces required to build file type plug-in components that convert native files into streams of localizable content, such as tags and text. It also includes abstract base classes and helper types for implementations. +* [Sdl.FileTypeSupport.Framework.BilingualApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.yml): Provides the interfaces for the bilingual object model and for components that operate on that model. It also includes abstract base classes and helper types. +* [Sdl.FileTypeSupport.Framework.IntegrationApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.yml): Provides the interfaces that expose File Type Support Framework functionality to integrating applications. + +# Native and bilingual content -* [Sdl.FileTypeSupport.Framework](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.yml): contains basic data types that are shared between all the moduels, e.g. the ```FrameworkException``` base class, the ```Language``` and ```Codepage``` classes, etc. -* [Sdl.FileTypeSupport.Framework.NativeApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.yml): contains all interfaces required to build file type plug-in components that convert native files to streams of localizable content such as tags and text, including components that work on such streams. It also contains some abstract base classes and helpers that can be used in an implementation. -* [Sdl.FileTypeSupport.Framework.BilingualApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.yml): contains the interfaces for the bilingual object model and everything that is required to build components that operate on it. It also contains abstract base classes and helpers that can be useful in an implementation. -* [Sdl.FileTypeSupport.Framework.IntegrationApi](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.yml): contains the interfaces with the functionality the File Type Support Framework exposes to applications that integrate and use it. +Depending on the conversion phase, the framework can process filtered content in two ways: -Native and Bilingual Content ---- +* As a stream of monolingual native content items, such as tags and text. +* As bilingual content in an object model that contains source and target language content and is delivered as a stream of paragraph units. -Filtered content can be processed in two different ways, depending on the phase of the conversion process: +Native components read and write content in a single language, either source or target, from and to the original native file format. They also perform related preprocessing and postprocessing tasks. -* As a stream of monolingual 'native' content items such as tags and text. -* As bilingual (source and target language) content in an object model, delivered as a stream of 'paragraph units'. -The native components are used to read and write content in a single (source or target) language from/to the original ('native') file type and to perform associated pre- and post processing tasks. +The bilingual content model supports processing during localization. In this model, the framework can associate localization-specific information directly with the content, including segment boundaries, word counts, and translation memory matches. -The bilingual content model is used for all processing of data during the localization phase. In the bilingual content localization-specific information such as segment boundaries, word counts and TM matches can be directly associated with the content. +Specialized converters handle the transition between native and bilingual processing. Converting from native to bilingual content builds source-language paragraph units from the content stream. Converting from bilingual back to native content turns source- or target-language annotated data into a content stream. -The transition between native and bilingual content processing is handled by specific converters. The conversion from native to bilingual content involves building source language paragraph units from the stream of content. The conversion from bilingual to native involves converting the source or target language annotated data into a stream of content. +# File type plug-in -File Type Plug-in ---- -A file type plug-in is a set of components that together perform operations on native documents. Which components are used for what task and how they are connected to perform different tasks is defined in a **File Type Component Builder**. +A file type plug-in is a set of components that work together on native documents. A **File Type Component Builder** defines which components are used for each task and how they are connected. -A file type plug-in is used to perform the following actions: +A file type plug-in typically performs the following actions: * Reading the native file content and converting it into the source language representation of a bilingual content model, which can then be processed for translation (extraction). * Converting back the source or target language of a bilingual content model into the source or target language version of the original (native) file type (generation). -These two types of processing can be combined as part of performing conversions to and from the original file type. The File Type Component Builder specifies which native and bilingual processing components should be applied during conversion. When reading a file in native format the native processing components are applied to the content stream before the bilingual components. When converting back from the bilingual representation into the native format the order is reversed, i.e. bilingual components are applied to the content stream before the native components. +These processing paths can be combined when converting to and from the original file type. The File Type Component Builder specifies which native and bilingual components are applied during conversion. When the framework reads a native file, it applies native processing components before bilingual components. When it converts bilingual content back to native format, it applies bilingual components before native components. -Bilingual File Formats ---- +# Bilingual file formats -The framework can also be used for reading and writing data stored in bilingual formats. Bilingual file types can be treated like any other file type by the framework, they simply process data directly in the bilingual content model. +The framework can also read and write data stored in bilingual formats. It treats bilingual file types like any other file type, but processes their data directly in the bilingual content model. -The ability to write file type plug-ins for bilingual file formats means that you can support file types such as partially translated TTX, ITD, BIF, Workbench RTF, generic XLIFF or any types of 'home grown' file formats used for storing multilingual content. +By building file type plug-ins for bilingual formats, you can support formats such as partially translated TTX, ITD, BIF, Workbench RTF, generic XLIFF, or custom formats used to store multilingual content. -At the time of writing, standard file type plug-ins for TTX, ITD and XLIFF are available. +At the time of writing, standard file type plug-ins are available for TTX, ITD, and XLIFF. -We also use a default bilingual file format for serializing the entire bilingual content model during the localization process. +The framework also uses a default bilingual file format to serialize the full bilingual content model during localization. -SDLXliff ---- -This file format is fully based on and compliant with the OASIS XLIFF 1.2 standard. SDLXliff can store all metadata available in the bilingual content model of the File Type Support Framework. Standard XLIFF constructs are used whenever possible, and valid XLIFF extension points are used when necessary to store the additional information. +# SDLXliff -The SDL extensions to the XLIFF 1.2 schema are defined in a separate schema file, which is embedded as a resource in the assembly and used for validation of the XLIFF files when this option is enabled in the file type plug-in. +This file format is fully based on, and compliant with, the OASIS XLIFF 1.2 standard. SDLXliff can store all metadata available in the File Type Support Framework bilingual content model. It uses standard XLIFF constructs whenever possible and valid XLIFF extension points when it needs to store additional information. -The SDLXliff file type plug-in is defined in the assembly ```Sdl.FileTypeSupport.Bilingual.SdlXliff```. Note that this is treated like any other file type plug-in. Applications should not need to reference this assembly. +The SDL extensions to the XLIFF 1.2 schema are defined in a separate schema file. The framework embeds that schema as a resource in the assembly and uses it to validate XLIFF files when the file type plug-in enables validation. - +The SDLXliff file type plug-in is defined in the `Sdl.FileTypeSupport.Bilingual.SdlXliff` assembly. The framework treats it like any other file type plug-in, so applications should not need to reference this assembly directly. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/filter_ui_settings.md b/apiconcepts/filetypesupport/filter_ui_settings.md index 29ef38eb6a..b448be63d5 100644 --- a/apiconcepts/filetypesupport/filter_ui_settings.md +++ b/apiconcepts/filetypesupport/filter_ui_settings.md @@ -1,28 +1,24 @@ -Filter UI Settings -=== +# Filter UI settings -To configure the filter functionality you may need a user interface through which any parameters can be set in a convenient way. +If your filter exposes configurable behavior, provide a user interface that lets users set those parameters easily. -File Type Settings Pages --- -File type settings pages can be defined in the File Type Component Builder while building the File Type Information. The example below shows how to do this inside the FilterComponentBuilder class inside the BuildFileTypeInformation method. +## File type settings pages + +Define file type settings pages in the File Type Component Builder when you build the file type information. The following example shows how to register settings pages in the `FilterComponentBuilder.BuildFileTypeInformation` method: -# [C#](#tab/tabid-1) ```cs - public IFileTypeInformation BuildFileTypeInformation(string name) +public IFileTypeInformation BuildFileTypeInformation(string name) { - var info = this.FileTypeManager.BuildFileTypeInformation(); + var info = FileTypeManager.BuildFileTypeInformation(); info.FileTypeDefinitionId = new FileTypeDefinitionId("Simple Text Filter 1.0.0.0"); info.FileTypeName = new LocalizableString("Simple text files"); info.FileTypeDocumentName = new LocalizableString("Test text files"); info.FileTypeDocumentsName = new LocalizableString("Simple text files"); - info.Description = new LocalizableString("This sample filter is used to process simple text files."); + info.Description = new LocalizableString("This sample filter processes simple text files."); info.FileDialogWildcardExpression = "*.text"; info.DefaultFileExtension = "text"; info.Icon = new IconDescriptor("assembly://Sdl.Sdk.FileTypeSupport.Samples.SimpleText/Sdl.Sdk.FileTypeSupport.Samples.SimpleText.SimpleText.ico"); - - // Define setting pages. info.WinFormSettingsPageIds = new string[] { "SimpleText_Settings", @@ -32,19 +28,13 @@ File type settings pages can be defined in the File Type Component Builder while return info; } ``` -*** - - -The ID of the settings page is defined within the settings page class itself. The **Plugin Framework** is used to locate the plug-in with this ID and display it to the user in the host application at runtime. - -See Also --- - +Each settings page defines its own ID in the settings page class. The **Plugin Framework** uses that ID to locate the plug-in and display the page in the host application at run time. -[Implementing the UI Controller Class](implementing_the_ui_controller_class.md) +## See also -[Implementing the Settings UI](implementing_the_settings_ui.md) +- [Implementing the UI Controller Class](implementing_the_ui_controller_class.md) +- [Implementing the Settings UI](implementing_the_settings_ui.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/generating_the_paragraph_units.md b/apiconcepts/filetypesupport/generating_the_paragraph_units.md index b899ed518b..321a1bb7e3 100644 --- a/apiconcepts/filetypesupport/generating_the_paragraph_units.md +++ b/apiconcepts/filetypesupport/generating_the_paragraph_units.md @@ -1,14 +1,16 @@ -Generating the Paragraph Units -=== +# Generating the Paragraph Units -In this chapter you will learn to extend the writer class to output the actual paragraph units from the intermediary (SDLXliff) file to the target BIL document. +Extend the writer class to output the actual paragraph units from the intermediary (SDLXliff) file to the target BIL document. -Modify the Function for Processing the Paragraph Units --- +## Modify the Function for Processing Paragraph Units -First, we will add the required application logic to the method ```CreateParagraphUnit()```, which loops through the paragraph units in the intermediary document. The function is supposed to work like this: the id of the current paragraph unit is retrieved from the context metadata. Remember that we added the unit id as hidden meta information (see [Adding Context Information](adding_context_information.md)). Using the id we will determine the corresponding ```unit``` in the original BIL document. We then call a separate helper function, which replaces the segments from the original BIL document with the paragraph unit content, and thus the segment pairs from the intermediary document. +Add the required application logic to the `ProcessParagraphUnit()` method, which loops through the paragraph units in the intermediary document. The function works like this: -The method should look as shown below: +1. Retrieve the id of the current paragraph unit from the context metadata (we added the unit id as hidden meta information; see [Adding Context Information](adding_context_information.md)) +2. Use the id to locate the corresponding `unit` in the original BIL document +3. Call a separate helper function that replaces the segments from the original BIL document with the paragraph unit content from the intermediary document + +The method should look as follows: # [C#](#tab/tabid-1) ```cs @@ -21,22 +23,21 @@ public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) CreateParagraphUnit(paragraphUnit, xmlUnit); } ``` -*** -Note that for this simple implementation we just assume that every paragraph unit in the intermediary document corresponds to a unit id from the original BIL file. In a 'real-life' implementation you should, of course, make sure to catch cases in which a given id does not exist. +For this simple implementation, we assume every paragraph unit in the intermediary document corresponds to a unit id from the original BIL file. In a production implementation, you should handle cases where a given id doesn't exist. + +## Add the Helper Function to Generate Target Paragraph Units -Add the Helper Function to Generate the Target Paragraph Units --- +Implement the helper function that generates the new BIL unit elements from the source and target segments in the intermediary file. This function uses the `BilTextExtractor` class created previously (see [Adding the Text Extractor Class](adding_the_text_extractor_class.md)). -Now it is time to implement the helper function that generates the new BIL unit elements from the source target segments in the intermediary file. This function leverages the ```BilTextExtractor``` class, which we created previously (see [Adding the Text Extractor Class](adding_the_text_extractor_class.md)). Therefore, you should declare a new global text extractor member derived from this class: +Declare a new global text extractor member derived from this class: # [C#](#tab/tabid-2) ```cs private BilTextExtractor _textExtractor; ``` -*** -Then you use the the ```Initialize()``` method to create a text extractor object: +Use the `Initialize()` method to create a text extractor object: # [C#](#tab/tabid-3) ```cs @@ -45,9 +46,13 @@ public void Initialize(IDocumentProperties documentInfo) _textExtractor = new BilTextExtractor(); } ``` -*** -Now you can add the following helper function, which works as follows: the ```source``` and the ```target``` elements are taken from the current BIL ```unit``` element. Then, the function loops through the segment pairs of the current paragraph unit from the intermediary (SDLXliff) document. The text extractor object is used to retrieve the plain text and the tag pairs for each segment pair. The ```source``` and the ```target``` elements are then set to the strings that were retrieved through the text extractor object. +Add the following helper function. It works as follows: + +1. Retrieve the `source` and `target` elements from the current BIL `unit` element +2. Loop through the segment pairs of the current paragraph unit from the intermediary (SDLXliff) document +3. Use the text extractor object to retrieve the plain text and tag pairs for each segment pair +4. Set the `source` and `target` elements to the strings retrieved from the text extractor object # [C#](#tab/tabid-4) ```cs @@ -64,14 +69,12 @@ private void CreateParagraphUnit(IParagraphUnit paragraphUnit, XmlNode xmlUnit) } } ``` -*** -Note that we loop through all segment pairs, although in our simplified implementation each unit can be assumed to contain only one segment pair. A paragraph unit in the intermediary (SDLXliff) document would contain several segment pairs if our fictitious BIL format allowed for more than ```one seg``` element within a ```source``` or ```target``` node. +This implementation loops through all segment pairs, though our simplified format assumes each unit contains only one segment pair. If the BIL format allowed multiple `seg` elements within a `source` or `target` node, a paragraph unit would contain several segment pairs. -Putting it All Together --- +## Putting It All Together -The enhanced writer class should now look as shown below: +The enhanced writer class should now look as follows: # [C#](#tab/tabid-5) ```cs @@ -84,14 +87,11 @@ namespace Sdk.Snippets.Bilingual { class BilWriter2 : AbstractBilingualFileTypeComponent, IBilingualWriter, INativeOutputSettingsAware { - #region "global" private IPersistentFileConversionProperties _originalFileProperties; private INativeOutputFileProperties _nativeFileProperties; private XmlDocument _targetFile; private BilTextExtractor _textExtractor; - #endregion - #region "INativeOutputSettingsAware members" public void GetProposedOutputFileInfo(IPersistentFileConversionProperties fileProperties, IOutputFileInfo proposedFileInfo) { _originalFileProperties = fileProperties; @@ -101,29 +101,18 @@ namespace Sdk.Snippets.Bilingual { _nativeFileProperties = properties; } - #endregion - - #region "IBilingualWriter members" - - - #region "load file" public void SetFileProperties(IFileProperties fileInfo) { _targetFile = new XmlDocument(); _targetFile.Load(_originalFileProperties.OriginalFilePath); } - #region "initialize" public void Initialize(IDocumentProperties documentInfo) { _textExtractor = new BilTextExtractor(); } - #endregion - - #endregion - #region "paragraphs" public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) { string unitId = paragraphUnit.Properties.Contexts.Contexts[1].GetMetaData("UnitID"); @@ -132,9 +121,7 @@ namespace Sdk.Snippets.Bilingual // call helper function to generate the paragraph unit CreateParagraphUnit(paragraphUnit, xmlUnit); } - #endregion - #region "create paragraph" private void CreateParagraphUnit(IParagraphUnit paragraphUnit, XmlNode xmlUnit) { XmlNode source = xmlUnit.SelectSingleNode("source"); @@ -147,9 +134,7 @@ namespace Sdk.Snippets.Bilingual target.InnerXml = _textExtractor.GetPlainText(segmentPair.Target); } } - #endregion - #region "save file and complete" public void FileComplete() { _targetFile.Save(_nativeFileProperties.OutputFilePath); @@ -158,34 +143,20 @@ namespace Sdk.Snippets.Bilingual public void Complete() { - } - #endregion - - #endregion - - #region Implementation of IDisposable public void Dispose() { throw new NotImplementedException(); } - - #endregion } } ``` -*** - -See Also --- - - -[Adding the File Writer Class](adding_the_file_writer_class.md) +## See Also -[Adding the Text Extractor Class](adding_the_text_extractor_class.md) +- [Adding the File Writer Class](adding_the_file_writer_class.md) +- [Adding the Text Extractor Class](adding_the_text_extractor_class.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/global_verifier_introduction.md b/apiconcepts/filetypesupport/global_verifier_introduction.md index 5e9c9cd484..fbbf1cde34 100644 --- a/apiconcepts/filetypesupport/global_verifier_introduction.md +++ b/apiconcepts/filetypesupport/global_verifier_introduction.md @@ -1,4 +1,3 @@ -Introduction -=== +# Introduction -For more information about Global Verifiers please see [Verification SDK](../verification/overview.md). +For more information about global verifiers, see the [Verification SDK](../verification/overview.md). diff --git a/apiconcepts/filetypesupport/handling_tags_during_segmentation.md b/apiconcepts/filetypesupport/handling_tags_during_segmentation.md index c86f3793e4..a5250922ff 100644 --- a/apiconcepts/filetypesupport/handling_tags_during_segmentation.md +++ b/apiconcepts/filetypesupport/handling_tags_during_segmentation.md @@ -1,51 +1,41 @@ -Handling Tags During Segmentation -=== +# Handling Tags During Segmentation -In this chapter you will learn how to process tags that appear at the beginning or end of a segment. +Learn how to process tags that appear at the beginning or end of a segment. -Change the Way the Segmentation Treats Tags --- +## Change the Way Segmentation Treats Tags -A tag such as **IMG** may appear right in front or after a segment, i.e. the parser might have to deal with leading or trailing inline tags. You should always try to display as few tags as possible in order not no clutter the editor view unnecessarily. This is why leading and trailing tags are not displayed in the editor of Var:ProductName by default. +Tags such as **IMG** may appear at the front or after a segment. When a tag is leading or trailing, you should display as few tags as possible to keep the editor view clean. By default, `Var:ProductName` hides leading and trailing tags in the editor, but displays the segment content. -For example, the following leading **IMG** tag would not be shown in the editor view, however, the sub-segment content would be displayed: +For example, this leading **IMG** tag would not display in the editor view, but the sub-segment content would: # [HTML](#tab/tabid-1) ```html Open dialog box Click the Open Dialog box button to open the dialog box. ``` -Output in the editor Var:ProductName. +Output in the `Var:ProductName` editor: ![SubSegmentWithoutTag](images/SubSegmentWithoutTag.jpg) - -The user could set the display filter to show all content (by selecting **All content** from the **Display** dropdown list). In this case the leading tag is shown in a separate row in the editor: +To display all content, select **All content** from the **Display** dropdown list. The leading tag then appears in a separate row: ![TagShownSeperately](images/TagShownSeperately.jpg) +You can change this default behavior using the [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IStartTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IStartTagProperties_SegmentationHint) property on the placeable properties object. By default, this property is set to [Undefined](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields), which applies the default segmentation behavior: leading and trailing tags remain hidden. `Var:ProductName` minimizes tag display to be more translator-friendly. -However, you can change this behavior as required through the [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IStartTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IStartTagProperties_SegmentationHint) property of the placeable properties object. Unless otherwise defined, the property value is [Undefined](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields). This means that the default segmentation behavior will be applied, which means that leading and trailing tags will not be shown, as Var:ProductName tries to minimize the number of tags displayed, which is usually more translator-friendly. - -You can, however, set the segmentation hint property to [Include](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields), if you want to make sure that such tags are shown in the same segment as the actual text, e.g.: +Set the segmentation hint property to [Include](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields) to ensure tags display in the same segment as the text: # [C#](#tab/tabid-2) ```cs -placeProperties.SegmentationHint = SegmentationHint.Include +placeProperties.SegmentationHint = SegmentationHint.Include; ``` -*** - -You could also apply the value [IncludeWithText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields), which means that tags are not shown unless they contain localizable text. In our example the **IMG** tag will be shown, if it contains localizable text in the **ALT** property, but it will not be displayed, if the **ALT** attribute is missing. - - -See Also --- +You can also use [IncludeWithText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields), which shows tags only if they contain localizable text. For example, the **IMG** tag displays if it has localizable text in the **ALT** property, but hides if the **ALT** attribute is missing. +## See Also -[Processing Placeholder Tags](processing_placeholder_tags.md) +- [Processing Placeholder Tags](processing_placeholder_tags.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/how_translators_work.md b/apiconcepts/filetypesupport/how_translators_work.md index ba7c497c00..f02944b652 100644 --- a/apiconcepts/filetypesupport/how_translators_work.md +++ b/apiconcepts/filetypesupport/how_translators_work.md @@ -1,43 +1,33 @@ -How Translators Work -==== -This chapter provides an overview of how translators work in Var:ProductName and thus shows the File Type Support Framework in action. The following pages provide basic information on a number of typical use cases, which will help you understand what custom file type plug-in and verification plug-ins should be able to do and what kinds of scenarios they handle. - -Common End User Tasks ------ -Below you will find a list of common tasks that translators, editors and proofreaders perform when processing documents in Var:ProductName. Note that this SDK contains concrete examples of how to implement the functionalities listed below in simple example projects. - -* Opening single documents for translation -* Creating projects and processing multiple files -* Merging files -* Moving files between machines -* Configuring file type settings -* Using context information -* Tag display modes -* Using QuickInserts -* Verifying documents and reporting problems -* Previewing documents in an external application and within Var:ProductName -* Saving to a different file type (e.g. saving a TTX to native format) - -See Also --------- -[Opening a document for translation](opening_a_document_for_translation.md) - -[Creating projects](creating_projects.md) - -[File type settings](file_type_settings.md) - -[Merging files](merging_files.md) - -[Moving files between machines](moving_files_between_machines.md) - -[Using context information](using_context_information.md) - -[Tag display modes](tag_display_modes.md) - -[Using QuickInserts](using_quickinserts.md) - -[Previewing files](previewing_files.md) - -[Verifying files](verifying_files.md) - -[Saving to different file types](saving_to_different_file_types.md) +# How Translators Work + +This chapter explains how translators work in Var:ProductName and shows the File Type Support Framework in action. The following topics cover common workflows and the scenarios that custom file type plug-ins and verification plug-ins should support. + +## Common end-user tasks + +The following tasks are common for translators, editors, and proofreaders who process documents in Var:ProductName. The SDK includes example projects that show how to implement each capability. + +- Open a single document for translation +- Create projects and process multiple files +- Merge files +- Move files between machines +- Configure file type settings +- Use context information +- Control tag display modes +- Use QuickInserts +- Verify documents and report problems +- Preview documents in an external application and in Var:ProductName +- Save to a different file type, such as saving a TTX file to the native format + +## See also + +- [Opening a document for translation](opening_a_document_for_translation.md) +- [Creating projects](creating_projects.md) +- [File type settings](file_type_settings.md) +- [Merging files](merging_files.md) +- [Moving files between machines](moving_files_between_machines.md) +- [Using context information](using_context_information.md) +- [Tag display modes](tag_display_modes.md) +- [Using QuickInserts](using_quickinserts.md) +- [Previewing files](previewing_files.md) +- [Verifying files](verifying_files.md) +- [Saving to different file types](saving_to_different_file_types.md) diff --git a/apiconcepts/filetypesupport/images/TTXandITD.jpg b/apiconcepts/filetypesupport/images/TTXandITD.jpg deleted file mode 100644 index 0d03f83a7073724a759f476ee3aeda7a320170e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91757 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
=mS&Uk|A69G=E}1_5eaq`NDh7!%pNL~_o9x} zze!+qXJ6+0j!*RgrZNTJb97f`lZ&9CMg3Obd?HzdD!TmbXQm~u{8by{9HMlk4@-F zRNDtboI@JD#!+m?`XgacYG2ZGLZUzMW>f6|A=x#GqX|a9tbyg{beZetelQMMedal4}o@BAEMx%((3&eUBfKrLH-TqC>q( zOg|L7=_m6Ruya%8<%dzqi9$yri(*4FpOBP6)cVH2p+(FuTUiwV?{);bAW*=MtBYgK zIK>!=ojwt&1(I3~@NDX2%{87@4Ux$#5|#FHaW;eiCLUz?~XC( z*%}SRe>B^>K|_n13h;XuqdQ8Xbm(j_KepyoRPSvvEF2koN=s|rj6Bz=uP;tIXzh|2 zUktmS$d?Lxtv$io2%k2z-!^drp~yJb*7HLspvKEbuwH$AHZrp9>PmnU%Q*Z&mp8XU z!pX2_09B3bgsLq!z19?H!8TDVQ*4zcFIU;pPz#;CSk??Cc@yREwTR9EW^4Ro+Kta8 zS_4q613H*){#*k>Mv_hoc~n%{^>b+mY61x1&Y*im}wikU`8Z;25Hn$&CGD98T! z?qloUopuKB!Nr|82~u2dPI`_A4Q^V!NztIHL!I4=P>8$pKu`Qh+dfY~J7Y3EnqqK$ z7dsSxdXzH~&4MuN)kq0KeY03<3xu_q(7vY|+}|KviHG)kgk_&Kd!KVB7>TYf5|YWv zr-YpSI(2B*(X0#!I?~u+PAdDW98%4AD57{{l_!5VSFe@@rBpgHqZlOxQFa`?AJ!!? zqGfg4>GS7$(wk+yM;$^Szw(pN9-tt40F-T0NCcgR9zD9Zj)L35% z>77PCYy%x?#r_vlSYy8Fd%E!Hj7)ggdcG6hP&oa&w}E@;>HIh7Q^r}&&hss>bmVVU z`2XsHCjK-INcI9a)@P08@$H>YoA7DuGdB9)o3zM(&G}Ea2Il{Z_nDkGHbO*!J)$M{ z$^4lHSm1!Wm2CJ*u!epN4r%9(`~`K|qx|#3A1xqZ|5GnnDYLXSp8*zN;Z?fGKY=+E z0Z8aSh<=?oSKUBH#*D%`;foK9!biH1|K3V=ClWyYkdAriI+l>z0uBYjx1=rEn zMXfaPwj^8h#92({MSZ(X@l*s%L~w;c7=|keYsk8DN*c4+Oj!xz@fC{tW|Vb6@9NKY zAx2^sK}iZGp>HC#_mcN*ohd$Hf3F=HqVK_8HkAhuew4T1!amtX%80f=5}%T_{ERX& zs8_*~Xg=fg9irk$bh6DNJR(3o`fOkM;K zjvMW&kJNEKNL-t`j1_@Xy%sNz#US<5Wen7f%qfIl1T1q661&f%7Kp;DxC?m7S*C25 zy!$o)YuBrd_!W*rwo16}%E7_1@*zytCHm1RUlldIb6BnE8hSzMJ?W@2XVevm%0PCJ zC>i?9ejc!7FYk!+jEyw6>Ub0K!qV6UqfaMVPWBR2MfxJ)$2#@wh!4JG-v(1Fz&pVM zG++-BOIiVB3&ynLFP4j$Q#OY29F-bI>ZRR*49dt27jm!(DCwXrymPm@^GCg+r~GT@ zNr6LtPrT!-NSEuhEEmHrDvb`rhL3~m$#W@vby4bTmalRT3S?^nG?ebhB|^3(yWqM` z5Wj>UWL0(um|?AyAKvTj)hFfr|ApZ%;QpEop#HZ`0B5UH8Pw(ekRd2gguV3}6z_@t z^6d_~$R17d-qpW29Jjg!m;lDjgrQTPqAX!Qi9F1u+fcn3&StWuvx-cpww_? z?5d_H?^tr+z#8%P6zh)Mw%bNSV4QLbKH^hr5+Wi+-qa(NZGmN}J5H7tSbuo-Iwo;g zwUpi_Iu;2p2J$fc!x+#TJ8Ws46IxVTx@v~aw$ERy-n`L7F`qm34`sj0`c{Sc*$yLr zmNE4V*7l#_#%XH-I$v*g^_`L)AZoYWb-g#uz=_M#QrD`9B(9MmXbEpzgFR(EkyrAJ zu}ZH!BT|qo>aZ_6sE<$1iYqHEz**;)V$m9wQvFc)L%SVD#R&vARr}KkP4`s%oI7YM zsjCyp79F?C@`AihdVqGJ9;zk+3v zJ1jMfzwWq9f;B|;@W~@wP`F$yyY{R`(Sk27Z8y)WP^Ks=V)J5e5HpUp0;Uoh1j}>h z5hLfQxOOWv`=BUOUcV+1z?0or7o2l(GE2?i2iOJZ$ENu^prcFB!=KdlKfZ6nBB5w8 zb5}Jgs=)!=i7^sWk3ix(d!M|dNxwzUB}aIfY3Y#4%tX|(u{1`E9LEd@jj@AwdGpd` z3xjbAQ_wkc|cNC4YX%sI0U4+Zw~0w%4IB!zk0A zpVp*T|HFS|R;}0LWa^}A@Tu%HGL@yayUdAzoV0kmERKtyP?J$59@;QVB zP+9oB8vmlX_3uUWkIp)L#70uhQ)L>ngoVkt=KZL!s6@uEGdg4E3s39{y63ngMhT%- z>Mh*duWg`u(pqLJ5ATsS9I^ChHRSmT1rwni3uj~9UWh#&Eln;7OeX4!>I3PBzoJ;+ z{rV``oOQuS?)x3R>7^T?jHb_%Cnu1ZV-Ql|Aa*5#!>=gM?wp_U)7T8K{jUJ68CPVg!1z(+>*@ORcrC+WQTHy}zOflKF!-($q7YoYk)B?<*yP#NP~uRk1yvy7JGjSAx<(M9MbL#2UH- zbVJ1lh9lbzN!C%Fln@#<4LnkMci|QXZdOowB1lPxNqOyEm)oIy!0yMU+E%|ocDAzY zp8?3}*wpW}SwDrB4=A8_`MHgZ;C2V9H8$5JNKSJsg_`Fi_PB4KIK{e53N+%qYH$O; zR==djeWW|SvmeoR<3aBEO@tdx@wOa5!UKghupY)`anQJ!t%s=_8ys7_5(TB4uYd`SEiIg{Dxt zjaly$yA@8t%8-Izeeh#L+LuwyaA_~Ub*O1NV((gIkGYYaf=hPE^P$wz@@l$Y#T&L8 z0b9XWZIOO!HY;)6eaOslhn`zrE|EdZsTm$%gF>|k)wQ^HG6xgnqf zlb_!Lm7MH-JnxI}N(6!KFAR`g_kj_u>WnzR=k*q@lya9J$Z$~FB3YT zpT4;+V&o!a%!si>$@OuL(05Uqh?Q9H`=j)DO$L^a{&25M#r_-XhI(zObu8IPx_-#u z#dj4OK*FsX*fD!%HGV)_WJx01+Fh@(zms!886&QLBqaNIYUJ1bLJqVq-+Y!W|9#BU zqWD15uF*Mu6NNim$>QU?lCR$wQ|Vs7!s}iPt)-00w)Qua&g$3k&-N z?WN$dfrbdODSWJ^0isB{Vf1C&Utq>58xcbL9%5l&Yo%*22Z-kiwoQ7@&E7TC*2PSs z6gL(mOL>n#8C%LqK5JB{D#Z|&W~za$Ft}?Ip`4c|Aii3?G;j{rtl5BZm~Y!mz~k9Yo<1 zzr}7mrwNsDq7*+#>})xkV_LlK21!?aQ>AUmGA5;G2l43C+-G_MWsa*GNucFCW{)A} zK%Qk`EYj+5Vh;5c$;U7OeO@w?@r~|Gue$yvdJZ3pUQ6%L${V*mQ4m;qhvVZV$Cj_&jF}k= z(0JxAR*h=@T>Eih8%7dZ8^AvP#Gsf&F%h+jpr^;ITe+e2*a_L-U@PVQdeFwlGkD6g*{VfTgOo7tC{-vx!(}k{uk5A z8Z!;iM=zNU)&ti$Tn8(URJPH|7ls%H1hm5wEW?s<3@T=1!n&ykumM(Mk zF}iYu$5n&OvFnT0nc?SG^O1|VO;J0!Yw1Q;+5ePY4VLp{Z~}Y8FH+EXsLYB_NzDT9~Q{eX@%l{ zH0XX==DQ=ohrMk-H@?*;JkbWHzR#_e%vsmuoQMM2<#1at3QkQhUkO^Fg^?J4VZ5C# zNQ8rl7kZT-p5LllGMY6h3WOji2d>FDq1gw;WIEEl^y)98YcZWWw_{_&P_KB1Wj%$m za+eO&aNcMqjD&Zjb1Jb68@lydM@TFXPNk}i&OQ@HcB=_t-^M|q=;;ZXPcfyb(qAl} zN^|skUW*a;=W>nPZ4(_2+}PqRAGkD`G+UTn^Ca)6UTn$LLr%y7tv;Ric6=dTf`K7A zrg3PNVdqwSfz!0oK>r367qJt{{`}gqM;XZ>Zvgf zl3Baiu|MKt7FOrEO24CV?a~^_V8?TYEK51`u%twS*Lm$4*U?$SEj$YkJ<{Xy=iRy# zFa)@(WE_dVV(8!muYZg%PR7IzOkC)sc4+bV`LpSyzpnB7X-5 zQjF29+?=(qeT>_Fq@YesGmr&N;i$cOu4&6i%K6thV40owPg9)L9zVyGtXeoOXbrGE zCG!wTzuQK@?0vLfLR<~1)o_xP?h;L^g?e0{&@u^4?_0NNTMi<7wJELRD!eG7S;LB% z1GH9OZV~#m{t0#YKNXn{PCdWf=Zk8MSRLFiXC&cy?!)fMy^y-#6<07!nvh#}AWk6m zaQra&=xPTo!1efV?7ekVo9&*k8;X_U6n6>5-L1F;iWG_lcS?i16f5pf+*;hBSa5eO zPH}g4e^0t+zx#Xl*)wOpwa&NZ%vxvu$O>TrPo5{_&hP%ob-gWe^kB8oF3r{wUI4qT z*y!H*VF&_BhnM_1@wx)RRd^(<+M~EJAc<2*Xx^P9L*6F60$dZudXW}6qMaQyHoooOXkq}$+kWwJ>hBb3UtLWe#1Y(1$-TXJH}eQ$ zjm;N#6#ZH};uMJ;=}PIm==V5 zMzQDlazs_~Xq&MEt7^54s4~Hz|5F=NnT_7cxvrALNoUj$CmAgpTVUc0;ih+CA3Cs* zUmFe>sQ=BeM=fAID8=2x*0BKQ2>1h#fpAeZU)vNCN1z^)gmY&>;zy!gC1`pkeLXvN z)%J*eWxI8+HU6LPQIoxp3;J)Y96f#PE$re;U6gid>bTPT#}mZvfax~o3vo!uxc$Pe zCWQw{^D-H>j=;KDv*Qol{ShY1O)&xqaAZV3|90KB!Cs)+iOV*0>2-wIa%V7;75eNv ziwVX#B0@++35{1@Mr`aD`Ix~0j54(OX5zUC{5V=5J&qIw#bo{NTBN62Z)H;<{DTJY zUEQ9T+81!xGO)uFYrV?hcA*oQKbze%Z2)c==h}5PNT+ zrEvx?b3_Oq0Wha%^rw&ocg5^I^y;>JV?lWz2992RfIF2Zl!`9jFDoi*uh&z#Bln0U zinbXi_^N4Trk{&t;e|p##u6K?Od#whN{Es#>^#|v zVRsN~6!M_Y_6vlOnQ$xGW_vDqu!?N|?f%;*imP9Vk z=%F<@%#4|Kh{|z2Y1pfU0$upK47m$cudQtK&TPJ(J+hwRXB6~_Oik>$h7&WM#A%cB z@x#ditL*?M2BL0`S`&|wX!tAmHG1YppQy2QvVZA9-ceH-jyF~s)4cO1G;?@4FgB5@ z_@HPm-8IAQtwa}`P#C%)HV zGyIk@kG@__{sg={;vvfZkz^#3&B(oY<+e|3T$m!;T47B=#AbB$F4b!=albmL7vw;| zdaS(wyhnV|8a;j4z#~Va#UpgYX_@7qY`RZq@BgZ?ioIiZ(09{Z-r4e zU2am1hY{-)^Wrqs22YiTWy!y03Qw~-EqIebYSAT?qfS)LEz%UL3DgeHX}y@u8MrQ} zcV60YO~z{*bJ*g{a)Qbz(vBYoRTS3dXCD!5;psD%_b0mrTgtx^WNfd8FO>lU*l~wAte7IYwuVqDCmiRCv zN-QLu=guSS%N#IFs3JLJ#X->X|~ zaV%A9t5+;1@1jw+jI559NDv&iWt1t7(1^Edj=Uc^)~w5Xdh}^pri=+x=lk$})&#mT zpAaLO$@v=Nnl>SlW+KvAlss2FyHY5_hGF?u^#ay5vA$pMJn6fe1Q9~s_*9o@ha^|I z8&Rn!1IgB^_yuq;PZ6-Xo?#))=~6?|5kc{3iVeQT;_k1ILXrj&b@@wGL~+QOsBF{3 zS}U}sIhEnp_uv7yH#m#_0H_8?``s6;E_9edBM5`%lFZ>keTt{av+ONcYVx=ntLf|0 zdU7nRZDAn>{1XlDBvom?P4n5u`|7wku;6M7x-?nM)Ug^)&$GZHW}rWSk*=VvH8|d^ zk=wVG5ur8$Z}VAi%YCoCcVs&a{b(z4xODB%+$!gl3<^h;W8XUg7$~{Zjjen5nM~0U ze1;st_G)iWWSAgTqQi#FANCP%|0&aGpfk{=U*vvf!|j;60a}$LKAkhQQ;&r%@&!qH z7((gLsRnBYX`>n#jEy+cm~8QzXI-J*TKNKDg`C6*4K-QWvc;>s?%7HTGX0>UBFMRc z9Yx5eb`&>Uu?VDML~b&k>xheR>&Ri4*=%v%Bk&^!|WsFOk^q8K=-3gV5jymZ(TL_yBIF% zt!kQ27f2tnl0GkHHMRG+-nv_Dfjg{AKPD!Qi$f49r3|UJAfqO%BiM#+9djQjy%k9$)be=kEdpGs#(K^s!V$B z2W#&)0uZ2!{~PH<6B~5}xlPi+WCZW=03GcMei-P-rz@0}t?ATfcH3!Wl^=fax^cP0 z3RtD2&}lf9z;xo~9`cwLO8ImaAKZsmlIP~oCsWq~{c)j6G5}wN^78x)N9F~#Kj4G@ z-IzyrL-h=}4?l5ey-XF=I^3!}bA})Cib^&FLBkRi(gjsjR+5I{O$*#ht)a1tZo%D5 zj0XChbwjz?zZij4)NlfI9aIuoR|U-Mj{QXnOIOMlu!)+BeRP9m@7d+qyU)SW-`q6F zknYd#YEehzug|EXz-b*=4zb5`xqZY)y&D(o%$}Ku%51?brh1y6CVS^o(2fHgQ4s;$ z?)on&`2=>(^G=s@SPQ=Qu?(Qwqg5>^wHpe@%8ggU&Eb66Sgy5^F_vO6fQ|J`pV)*lJWO|Z|bKkoS6qA_Th!8FnEcv+#k#55}R$C!;T zoE{<`FBs83j6VOjM&d=nzg4;LSpKYb$=Kcz!B)V737;nn#^!%uqH_2iBNBbC_I|5t z_5WApi^Cbeen=VXU;z2L^*d_@YvO$TFA_HhFv>FN2noTFDj}g^UT&@#$FUdFLf;4i zSvP#!Q+VsCUOzr_b)qp(&zzHxJZ!G+u6Xg{dx$V~e2s$uqBDhLg#oE0I_b%EQD^6O zKWm2eWP+Dy0?I2dhQGOcR%v_7=sXLZo`WUrY~NUJX*j43y091j(6I7-*9nh=Fi?YD zwrfA8{YYO|Syf+Kkugx6ctr5W9D>TccO=8vV&BeHoscL znksL`JF}*`Mhi6{JOJcL*5N|ZEAfT0kP`ZdIBsX{X=`#xnYG&Xx=e;7xndKHgZDTU z`JuPfT+K4@?U~obBn<}d!QX0ce*pa7d>Y&E!JJ=Q5_j}COOuM-iY?2-{(NXIRt1?m z%!w;jKqKepuQpnTaH(lWrs;7>?3PEHaoYy-YrN`5k#M~5)dZxkk{TMgy;#3T4QJr_ zq9^1$Tvr*cye!GQzZTy5C>YJruTtzzL`Qnblskd}bu9wx$y7L^H`4;YRH{cVLS;xR zWBhi-MET?uzD3IaeV2#$CxiFD;Qr{I?~$i9ji&N9mZt9n3A{Wta8CepEDNMMynk+^Hk0Qn_*pGpm=9F zO7C(2ESEgW0~;aKU0BiYLn^?Fms6FAq}4A#2^0buzwlSu(rTRxc$W_W z_E-`CbB<;=8$n~4y(qDYw?EpndC)2JCfUlNAEBKn>n@rqZBB)s%qm~Qh3-@!%o?m8 zN!&uDqEE_Hua4N<0k7o+lm54+~+Fyf=yH5a7i$|q^pR>|vBR!Acl72;5QOx+uMRP= zD;rSAhgOJ~<{0z#%2>y(^By)CB-1>@%1T!~1B*8&W|b;E+h`@lH!F_cr>|*4IaaGP z7sLWTv;`u$vxPzOg5ST zxH$fS+*6yTb=0OO)=B*)ZSzDHP`SFXG+cIlpb8r1nx@&!zJnG0^0=O;VjEjOg!}5? zz9cn?9HFjF>UnyGM^8e|&&{kpQMgM$SeNnxoT&dR@S*3QC#sJy6KMItmL^%W>~`HT*QPLAHF&A0xRtUf4Pa2+6|JRhESnd^SfnaC}99q9rkom%4hV zvee#Swq;|gO(Dvr^1)=G{9^<;Ty0$&G?C0e4J=0o_A`2jrrpAJ_e{RiH|pOZIm`6L zU@FN@XsgJ8jgv{{MR_-~&pcy5$IIAg8xs45JVD2U@QrksgvKFA<29@jJLCnamCvL# z_0=uP>dkUcvCBl$4o{W0iB+8OyCcvv=O@HFMeA^=-8*&d90Sbai!} zhFTH)4qvJPg4-OE@bNvgLCL9avxM>Ev3_xA zVX0$cB`B;>#o64GX|?3RT_xcD@_KP3`r~+Z7~#LSQ2(Du(M1!Fd~xVda;zQ9gcFhF z8IfGi!W=8%O${wW&Fe7pBooJj10tC-;xaJK8Qa;pm#6!b8ua}}M~tz+lE9~F2e0pN z+&Qf@e&nWM%ox#jFk(uGnf2e0*K$Ibz9vlGeYV2h`~2qg`iG+}di+P(jnhVGdAij$gR#M*^dNOco|LUW;0{X{K7i%x z!{nH`?+{|&xehn=yDkk4Ho&_>E|Mj!pQ*;SXs#yK%bQb)=6l<1zdzb3{f-dgf4+vWK!P*#kaqMqI%er>GPi|omU+}(kapi zS1&rsZ4DGE@Rq?JiCF^gf)zrzLmjPXOP1K{{S6rKRlYn{LV=JW`myDnp(2wr@-p7s zMwtTEB$!`VXAEt|0j%I;W;xmo;^mnCk!gpdg$UevJ$dr<>DjQYq6^kz7G&O=RBlP! zyp5_5UcZAV=6|>ZmRktGQm36CeknugD?7LxRQFeo`-NrP^+~q}_r$^k4sx9w0>UwGL2SD zJDksE}h}U62CxASLD8^qjHvXET04YND;)ul}`QQ0d3^JaO|X`(<+B>*tFT z{PwraFytUpNu(!%VI;{62wN8Qy1^9+PrG_= z&0C_XzwZmyG(vJ`Bkf^{saBgfzPSzq)5tI0xxOy(Vc}Y5NCDq!y54)s;-7`mS-VxR z;?q*5H^~sPy;A0H?>J^6=o;50vyiW}X6iSa$ZfSw$*YZ}Hay2lGc|kl07be3^$HZM zfED=yAHA(eaTGkcbd9+s##j$NU?0K9x4+_8k~;$FJ=-vz{L1R+H9+0gg(|m9=jZOg zP!rI4iPf>NfGu7#rvhc$4~LMz5cS5;qu z=-2%53Rj{oexJgcozK;(384g4jb%iI?~t5 zWi6uEmks+_e=!>TRU6>mi4KAs1&4^PF`NgM_?Y`x5DhOp{^GrR;9uFgqc}S|w{SUj zo$`S7n}$$G396^M`F@Pi{fN$71mQ>Gj8C?w*NeW%p2tlmMSH;x5Mld^*5I#-g9?GB ziDro!;+Gqv&;PuD_exp|~|CWrf*E%bC8 zzD@Xm=K zdGDou9x^+#)zKc72*=WH$e#;?C`rQQzPESf<11$&ywLKWV)21>3AGt|{BFasfsrid zV6@=5ivWt3Z3%t09?LF5 z%0I;a04Tzie@266#^}F3XpUM}xZ7;5JDuJM`Cb|Ei|6M0i$}yPwm;pXD(4;t;ur1n zWHk7x7mQbRDeFX+5c&1(2ZK~k5gy>AoehiEfK+_K8#a!V1Q~}~Azh)ezByHR+-&NUr~bjO6l^1L?dOVMorT#` z+TFH_gP~c;#yUao%~=lcfKW?r>$|R_*XR|sU{a_sXQs%W4^H5@E z2_s=_ZT;$6qjE^IXqjMHM5BKS^+oo>JJ-Z@(|sK-O1;$=C=2PP9$|eoaoZHHN%U|; zY)Guk>#d*OUiX*P07_m1)o{DGKsABdghq2mg!~oR!t-^}Yt|&5=rSlyAsPyOO_iy0 zRQO}~J)Dduv{|>VXfND07*7(~*kDO0s$T~8&*d(45?v~l{?{Wram(vGiF6NAT@ID~ z{4B8@CtBCfbU#^ZvknW@bRG-2j?X;(<^NV)FDf(js|Gr7eOoKjRJlfRkU^zS=m$)Rb1+(~05MQH zODGjoJCLi?TcAb}t+B<~<~8H&pSa6Mc;7Hp@}0(9hO<8Ze*@^OTKnh&OQ3gM&xx*n zrYrsHQ}{4bQzyl|?DmRNc|H#|*;q2^gC;ZoiLw$!&Cn%?2FSS|2-YsA5#OY@$D0SXF zPaA$@`YV3KYF_|@CXLOy7O7_Ag!6V?V zyeh-X-z!vN!T108RJ*-IiK|$PQv(iOe?EGdrlOtm#vscMdk}1mne>LvGMYr<9K$>* z_n>aT#O{WiGR`zyAz{X|DM*c}Ut`B1KHv*Hqs;VyuaZ^S^GP>(k_gjZK46P)f|V!N zKsKA1-0rG)qL#^9Oa6sxO>v0s>NWF^ntb!YS*1F(W%2u5V5Ow99<(3w(VIl&rj}cX z!aZ-;3uXCx7oCZh$}Zb5s8b(5I_T=IEG+BFeyReAH1Z4zNPQT>WZ}P)`K&6-op6{{ zuw#3H++;Aba@uG87q`$~JwuuaA64A^738GLwrj1|{s7b}L6*UK66+TvH0NEVs(HOj z%b!uxF~4F*<~O01lqoBXKXSQ$c19V-VY^O>{dmL#4HCF?=N2c-^XInm z`OF`7P7mO4ExI_TxMN9Nrt8qC>sO<)=zW8w?w2M16iOcDwJf#@P0~(L%>t(kr^@x$ zmTca3#t`OVnF~&f z2;_&SA*+Px&IPN>{<=~Xw{%Rhpb)s~i)+oRZLi4HOZRSX-J?Zh22eLw>)F136K(nW z!Gr;gnM^!%*`lIIeedeFL}VsHp>s-Sv0$8SQR z0J|++IN?>n#}~dw{eU(5IQ&$dCm3AIr(J~e;Xzb!a;LQ=&hn^igHsMRXp>S`NJIx$ z^9T5;wdDz<(4Uf}i;F|-oSbPN{EwDWWW?Vy$`#7r z2duP9u=!pjM>4Bu0=3#k{ZF=B&!-qye?jLF1Zf#@{Cb_8h)QO=?}8Mn(3qmVYihFNJkbYAGLqS2ZHi;x~fY2Gu& z$7gGSKn+*lJ~DTnBQ`OFmn)*$P35kGevpj@j~7S=>8I$s9IUpefB6`w&nuubRza)(Bh9eeL>BjwI-SA z<60($FDIX8*}Jyo&|;*5Z|n= zxELM*@E&oz#|(3BdNRguXhNE~(BtU93Y1xpsfyG3nQj3rZuPi`O4rODH!tly&TO06 zEpW~+I}YYeakb|z5orPsam)h^hiaezdf^?vi0dMwI`+2LgX1BIJfZ$adJT7e@B#vW z&5bQW`1CPpYWY-+42;;^1*_}fBfJ`8ZmXBfVpr{WHetUViT~;C|9$Zg_s_iFC?YQ=!poYM@>_J!wV(H_LS2&n(TeTo>Z!q)%vxGiq8Rg?fr_Q|x+-#p?9|=L>O4 zt8(pn4Mw01QKGispVIkvI7_*8g-jlS#GR<(eK{Dn8-6s$9pj!|-@8A9tA37!b% zmKERXQ$0g+pkUNcvToH+Y<}eSgK_r0N?b8k&m=#$YtQhZB}?F;Pf)ePT4+LSge9I= z9|=l(Z116k@C!R71a`MK+gwf*T8vfF-e~Bya8Ys^+tTqu(DW)SJ29gERg;8;p9B_* zHD2!D7%_RR=W=0q-DN$_Ejky*;TPTG!Joc(VZ9WR+h;^q=y{7fb!hTq%0<7!t0aW= z6VR=L6IVK!)0op#^&6<>SQVMN`cdR`bvO0UBWa$yzPSPWc`R=amMW|3;WUlrIPV)B zu)P+$DNr~)x0r&I8%<}252k{MrK?`7Nh)37f)ctIGaj_T9+ebMI94Dhae}EN$upVI z95)k%=m&wCmA4ZN-5P@L_AJSz(QEavdQnV#`Ap-Gfzv~56jrZyVMdbG##-wKvwDuF zC|CS_wvDcy)@GD)dgqFHM{f=Kx0HkBu@XP>>EOVr7JpQTf!0-NSkPv!7Uu* ztwCs${RWfFnMOwTUeC6Bd9MGuq&3^uCMs8|H|-IXW&mFh=~--_6w4YosX@!+bt9wj zcbRQ>IZTlI%B<|*^2+S{%(NpHSnrD zbMYMvHZ>JHz^(#x`^ z5R9;4INo+V9^608RR7UE9O71Feva+6x5Nx;p)1p!V=tL2!(ci&=Su|g?hlvm#r~xv zAxqoL1;UN%jynBenF90R`J*8J=%9(}p85*&!{VyIsjx(5f5iNp2*cmUhGeeFAVm0X zGT7w40QI%Nn4Y*kB)_#7!{f4NZ4XC}BY=O%D`Wo*EyT#(z5mX<_*?7ZpBBs9f8S!c z3u{P@(fmG}`G4@yT5o*r%J3Rewa*GCVZD-UB2`pXgSL4m(V zkTO#Dmre}ptW4yFQE3jNlsSA{>*Kl)MQ-uN)F{BO?yPc8R;DKS8MU%JywONVLMwPg zF|{QviiLFcQMjQ5e%k2(abOT#TRwoyw?d_Ll4^?e@*y-;+WYP5q7;@dQG_iyNmO!d zqe%=?^yJYqtmeSZostML1ra>tY0_Mvp*uZOH`WKd(_*H35ZO8$fY{Q%diSX>3C<6p zIOr3W_<~X*V?LF@hse~4AsCHEO}>Uoys%?;_O9R#J*&&b6~A$*X@FnRDqI(bPk= zr71VJ&EOBZWPF-o1~-e+G`UCRkle$?$%;v9NB52sYH(S3^uJhW&Bqa~E*lV&GPPMr zkKuf6qr{c&R}wcn^!#e_{E?4CF~3oC$o61Tb>znX$VShsYRa}|Aa0K}J8^RG4X+j& zoLC&6UK7fyzvH6DR$xt?3rB~&r^sW-TkG(^2%(Ebnc~((`aNCVgtNCZlO2hg&kWG! zss>NOH`=Tb*r@9dA8IUyU-|x^I6!klLjgEVr1i#Fi=sJKVBNadvMPWT;v!oaB2;_7 zM7_`C?L+qO$|@|0v#M=@r3TO5U}p5NHqumN*Lw?fTjlOveB|0Er<-*hL97C=?13zw zO{4InjK2G_(*}WnXf7p=k5ZGRk7^ixh1z3Q?wtO9$7MvJ97%nN)kL1y8EFoJ8%TM3 z^>p4*bzvKjR^a?%vFJ5YEiMGFr6W$t7Xg}_07}EzWc{%9`L@?(z1mqh>|S~)v&H1w zQs5MX*=DmgUD=k>ib{s=H}0VW;rR@g)U|)es=y{scG=1my76Q8t7b;mdW+4D#%WL7 zyZ3S0R5P-14H@kTxU8~+L~E}7eQ=({Q8(+o8IDF=^P}9*%GMh2Oy>54nVh~|bi?;V zX?=M3`XDmdG8Wb(SKEX8xwO6CSucHy-1oW~Kh9*Of0iERPaPezs`6JB)uZP=Wt>{Y^=;)n$PD;);#_J5DFAPuUyp_ zEhsinD0Xu=k(w^u9Iq&EZons$%3ph@%Fe|5^xfgxX#@YmTt9=gEoW-&W5q2Q4_?o1 zV}9vVorXTw zwCzLQOXE?$qR;mI^TuG{QxU%VkxF&t-|oe5VNkW$xUuIJIv9%$mRNi)@>w;w$1eU4 zhDRm|-pk(iJo;R|mWF>aeipq)$&TrS=@4H0e|7u&c9#B`?>C((68~KtO+k9hJ!?Z{ zZ%2ljV+Qf^XqZpxH&;zcT=2G_#N=(Z44`@bJa`I`RWu}ysD@ttzIXN$EqFW4Q(jDk zI`fP2JjmcQOICSK-?bF%aO$&Z5Tg*sq5U?WKI&~`=#X2~JRFI!tl-E`qIrP5hqR?(HL!sg4hu;Wty>>LX(>cLi6^Sn{@pO6w|x2&i|40SPoy7nA4Y{!J~`U4jN7 z+qHsQrJC2*c`2WcjX_kdlz_w10$LfdKLBo58>A~i8*P){C#mAqYNlwRFiebDNHy2p zmnhwI(Xn(>_^1~5Juhizd!*z_E#+&^p;U!bU?%~1x_g>h3!u(Hpb zoXu@k=%^RCgB7_CjYduV@uKAf$Mx@pW zqnkp-6Q3Wo@4~sP)^g5u48Nf$545=gR@rqUjz+CT-=DSg6a+^9s(BcCGWt|tH8Wz| z)6{h?1Wn%OX!}M4bV5*1euQ8Ln(!u-`m!|b8__%nE`CLjkvX~>fT!Z!+z{v|u1kP% zUym*xy+%J5!;FCok8PM#iES9n-zLA;Wob{_X*GuWf$tUndFVh(WPT z7YvAT8-!)S<@@VTr3i?J^kE>6eU63N@n*!A_XycsH`=a z``}U5i8=GO)EJv1M2_I(L_mWykVZtVR1sNi`j8tF<6yom#KsxbTZ8_27JU(mT1=nj z&F%2}?}SVd95$F0JQy=g3(CDSk4dY2WaVvTe*jjW>30b_8a?JgHg6h!(FV3=Ds7D= z!5If1KW#K`UheraHk{HH)wKK&Y%O_8bH+WR^-V$0ST~gX+G!)|UP+drDGcWq;r5y9 zR)4+o{Fu%hY(&CXw)Oo&eUTE<3HgB*+nvuf_U;UfKlDo1J3|BLugrn>li57!1;n;0|I^DBN>r!39b3#@6S`>Bo#G#$8!WB3|N$?O4`BJR{P`J5qG^5q+~m{FdwGHa-kUGhin z!%0Ve>8|tpqBixS?`^*vU5*$o_xX5o%TKhlq>m5<{mO$(;C3Pd)1S6Ky%1|(ht=`F7`*eA z2k)(0ZF^3)=^b^emNLC$MB<;%3CL9PM051u3kB9h?JAdkY>eEAOXD6fQ3NYQ3#5Gv z`DGHR$48dyyXw3WRX3?KJ-LQ>{KL_a;<|>|dpO@RheWE70)c_Bosk{G`{F}0ELwaF zrtr`$DRL2o-}@mE%Y0*|%ETX}=NPUXF%FxCP#u=^h)O=tqjeuGS${H6jPE&M>DT%e zBt5Zpo^5R5nb*otf$;f=@IxGoIm<44=Ud;Ji{%$7h826`Ja#ie$2LQGYR%~pZi}Sg~4y& z#^G<^#y>&|7*Zo?-e<1qZ%7Tsi-muSF#c|Ve3jige#shjeuep;Oy6}@{AcLLVH;&F z&9`KMPIB?d2g<*99;`-GVk5Kg6C22 z@s#;r6bu-Tgq(gLT?==@oq+s8seuYMk#JX5gWWO~nYi%1%)&X0l>lU*Bi-OIVXL(x z@(q;F*9n`sg0;Jts)@O9J=#m!4_t=+81td!8YUs%c1M>)B{6J+ zQsv8rJ$ROm0}&^LRTuXB2{$+zefx2HCHysAG|^Bw5KO0ktXk7HqCs!g$A-1jl+h{T zCJ_PhpA{eKk>UI|Eo@-s4-+ff+pIM9?4pLqEkku4el3UYP(I& z*|nap#7?}E2ZCi&b+OWTkyB-_hD?9NXb%0tDcaH$nufv!#KwZr*XFiQM~)-C3s;uQ zE>)#Prp_6@2CL>q&`Y=P;)$I^#Akx#Z?mkeR)=8QGu(w`ZQYiL*UU*WF9XlKi*>lR z5yiBkuY!b;5PSu#6gK2|DuQ&zLWG6*l4#5F1|(YQo5LuC9lMnx#Od=dCm}9L9THc&`v}-?5qPeW1D>Tk{M@9jebr zfqeN?3{4Ck(X{h}qSSSB%HkxCiE#CN0&S4+>yVVxUool7JKaDmPkY^Dr3E^GtuTvT z4Tyln^IXeue(hd2 zvtkwM>PI76YZ4jqE0;3dTelWWGhWD9l%4FiIB*Q?B&aBjUa#uc~R~D#VeW+sHBL%&;}3Di@&!vcnQ?k04vX`#?(Gu3-iZ zGz}9lX*wf^dXq>Qhnm&P4Fhg8La|foDYz1aod*Q+95=v1n5apDfnVJyroj;tPUaO7iv37;Lpv!_XY<+#H?rI-wzCpphnM7+o z5UwiU-ikC?zLeE{p|BpbP{mOSUg-b9>L8IV6&@!xK$(fm!&4E!?TLx3=VqbotD~hS z&F$cwfy4W>N)^(%0b6y+f^{}cXL+pltCanDtgko%Y5JtTw8XLe z!eU#A8;!zDO{9fVOWdY(sa)0YSwG&oSttz>R}_DQ^QePkjJ>MD>I2H5Gd*4AKB$&R zYRtuy+=;pVytz7pJ{nNiryC!ql`a$>>EhXjv(MW~+2F_RuGwGtAdGHH9j=u}H4r^~ z7Y?QB<>Z(s`UB8uQ6gJ*8%4IY?zXN+%|*P<5W)KgfCh`x;fCIQ?A1~rQ%iHj9r*ka zjwx^9ndI?G1P`~EF_BfQ!@O6yp%1sV_m)Iw+L^&9Sflwt4IO82Yi01m5?Axu$}1$U ztqL+E{u8|f0VWQec^|MYEb}h*XC7Y_mJcu>_&Ft!_vaVB^dqn%(`G$+D8uASJ(@{R zu>M7uiIL{Rzn?70XU&ej3Wu@7ci)5||2;cG75HB;q4h5r{XdUM(fbGB1bV^!{?Qgj zr{)s-_eZ&4bZWMLrc=X6=RLpv1v0<}n;iJz@;AtU`VI_Nt#BlIs0Uj%K!_fA|7{@y z&iJR`Jz^uxtWWI0iJ*K#jyUan-@8Wb zdph`1loNY4?5Yjhpr#GYOZqxEQ5$FQo{eijlwEHhg^}ZD#cw_}g~)Dy60yi|-XaKM zOCnP&LzpDh@kltUL7tkiAjDpM?ci`n;6-FoC|zM$$D8U>!uh7ajJb-8S8EzafEqCx zfxhzvNCd=l8C1KL!Pf1lli@JK^x&yFT<6LGjA@DixM--wPpx5FW*z7)ZK>?XRPA7*=K--XvAi);51*;HW0oMMA(SCaM%i zhR9IALI(;fD!H?U()>4yT(%%gFlN=l&h1^gxB4G|GU(lBa!HoYq}t*Il90F6#Y+lS zxbL-=k@G6(dqHNKYcW37#pY~Uzfoe<2)G2b#jB=e{ zbTRxsVB8J}Y}HhRUe{%!RkfWdwrnK~&2?}NI2nc*5X|T0yfyrQ7y=U`nY0_q!RLQ% zK`L<5$3}9oLyrDV`z_^t(@Tr@saD1)V3+# zQuq~T;#Vnz!Y2Q1;#Ks-{D-31rD)&_mO7&ZciKLVO*|r68KGyi9G4XCU%OxvmLAzQ zXR*Rn_Qh`X21a#ivV#3R(lSSa32p}AD2S=sXTQe8C1(!akr5rDNi!0k&D zGk!eR(s2uZe+JAaS|#9`t8ErF598IFlTpWckwd{H1Ru~xgPoTJVY{)q{R~G?WiZpW z-M4Vda#Z?x1T*w%mHLB%?1Pkht+X&bx&AMHz-#)L*cIVvnOkoovuqLwKggb2!xjIG zxtgW1Ns)1IREK}Gcln!tXy9QB!^ER>jsH)@x8Wtd7w$5n@TA}q9Bq7Vrx)+w8YZa* z*%vtxwS)UKFv-T|ODjqXYN4s_kZmbWcx=60ULmAU!ls5XQsMsYUDMB^iEXD|H&b|Z zze7G))G`ElrB8h7{77J3e4Bc&5UI%acA|+D|NZl~PI&ep%Fn7wc(0Mklt8fk)fbzg zXYAZ@q5|HtLKI5xsvM-nazeNubbriRjoFF{eMLIO%8bijS0HWu4P)WN-5*Ji?^SuX z@G7*K;p%fub5FGmT=~@wqH%;&Dy&)zDNtNO?aS{l>s8(vce&Ek5;YE*t?xNnx z_`4bVR4J2`_#PA9UG0UJIrp& z19k((vBLop8YLd>-Seq2H$%4Jlq%PNu(m zE#$Z03tE~LR=4~yRIuw&7Li&p|GhdE|3hpUu_kK6#!`&f0AK?MCkfhHxqnWMKbV`U z{mH!`ik=^Uo@-qIq_8;0lPHp4chf~nkF$?bd|!838Y|1}`k7|tB*!x1Ju?)A$d`P7 zoSKUde%qlhs)3G&he;I2vX!F66WthwBuKvV6kf2lt?6!RkIk9?(cAq-zJ%c}SOXd2 z2qm7W=1FL&^DA=;R(C8!s7J|z`8=^?H|6G>>!bMn@lk^4TiThG(VOae<3MZ&QqHKW zH*Y}Y&7ji7687As{7TU`0r0$YZV}wK5(qcrb zQyKM<1(06F-WQ;P1b~Of%W^Jzmx(l4ae1&1Y8rPuN|3tG-<>NmY~NpA{9V$pDjhB$ zUDXP;^k9&uzV_~j$~qLEMF6tqCR`JfPnvLnij})%s)9mlC+UL3C1{iBB`o#VsN&^%P;K(g9hFg z2s|m|eaD#aHQ{Q7u+=(Yv%tC~byII4bQb z73z|WP=i-bZBrP(%un8;TL1rxy|)gFV@uaZn*a#}hu|6{xCVDfunbTX5*y%09FA%$_?ld+zVfne*Ip=MSFZ={#9gwdhs#t@nFHoR{Qo zq&H3X_1n@Tz%hpITv!lGsc3K5o0*Ua4MV z?~dRo1T7b|UAeUD@Wl0M2xkQ5>PR z%pg^*tV?-Q&LWo z>|v#5`k>c)rn~Nh>f^81%xrHF@-~(my=@6tB%QapB<^G!Rt1V~(R3{C-TU#vtth*Z z>LM1TPneA8!h}irS8Nx)_lGN8Rb-fzcX9EW)-;($8ducS)dZ+<8`>FC4}@NR_73Ut zYZF`-VBI^qWA$S0ci+3$y_;UDX41Iht@L{nFz0Ei+z>lPms!yelc8=I%klWyol;q_ zaNDhRh0UIWQNKxmWQnl(YgrBP?PN=kbY4TM1V_ZKQlvjp9qEI7(vv8MG}HA#z;6bx zHkRkeavH^w3$5Z4YAE(Vy74dgg&tX5vFAV89g&+mxb{2(`q};ELA4b-H(qgf2#)=$ znosJYbUEyeCh*_tsoQNKeQ@2mbk6??u;eofl9LvFdQ(v-my=o9ozqYK{-wDXu?qq= zhqv_Ok8gR$OrJ`Ji6@IjP$x2L!t+d3KdEw1m?qDWEeWNSij!JS~Nl`vhg z)8J)YfQ7z|(D+M@ktMz;@yInM_6}4+_$Vc#$@(VJr}bm2GQ(Y%OEu^B2Se#vTKypm z`!A8JBNBSPAm}0T^^vckwa)w3wD=b-9H#A83}TDp$=s#!O7grycXp`r_It#{kTTsp zil(luuDQ_I%{*k+&t$)#*>ll20&)bu;6ot!1W0x}X|F2W8?U`|3r}Y) zo%nmg@hYrHtn7rckELm#4YhjI{%utDhluhBz66+J6n;t=0kqtdB3Cj_t+mJ=qtHNu zGk!yxxXo(;yB@)oru#z+Vuhc}S`Wpulhs%rf@5`PkJ)sY{fna0$iv6jE-62xFAm2GCuaD~)_nJBYi#XUU2W%b z8s7#hm3PvRIDNL>wBJ^+mYQzcdEfUTGCWvn@CMc*UmgqifSv=s`;DM8&=ZmYNJ9fRHhkyZTWHShZRjlYjQ^Biu|z?exfuC={|(=i~|fj z?Cs%v)Z2oS#3f!z6YmMZ4aIUSkzV;iL5-3X&tE=E>fY3fOkSrF9Pg=dTD6i~ ze=})Q#n1#ptv}jKnks0UIA)Anc)eV%4VS!P)Z7p-9#6y_are`4UkD zKUzyf3CH~W@RL=)&BgT?<3Vh6S^mvtdpBjfRRyxlag9BVoRZJcgd5`-QS2yu0`Z5l zTlviW%C^X(1k^;W$0?#$0rM{>t!>63_2X-5ucv&F`aSwE?>E~d4Q5wJNVIM6)CvV4 zJiM}BjT{KxHFZ&sAS0mVk*sV3Uj1HsnyjZ7K(v_VduJ*eL@%a#d77L-k{+E>GCb}^->hA#+m3lw2po3d>owA7A2Mx70p5mM*;AH%!<9=r0MB4t* zQD&n$Xr(w?Z-s38XGl9?&EoshfmsdYisVGj#eR_=Ga_a`B>#T>8x=NMK4B+ z$Ck7gfwoo9;&#*zkktgHbOomRWCG>}sD2Yd;`E(&-2*>;R?5mWe=k}VY`e4yqWkelAG>pX8sFVWY#UcOFK%=NXn;%<@}Y0)O6RMLvWUH zgSjMiidNi%Q=VqjOj+klOlNcwG&Z()vIJ0V{_jJp0fW%53tj0@Jh5iC_3Y4AZy+M3!m zmg9*OIS@g^Ywc##Tj-(orCQB^DEax^((}H`nFTG4P9|dZx{4@c$=d-@NdvJJGFxVm zG8(Ur>AROxz%xg)=4bzchvGQKzp;vX`nATjO)G@uY>P>p0+}L;JD-+1%HBcAu@z23 z?S-k0d*LpBbIJ!vMgh$u+Cgti_6>+#hGBWkVC+ijHs_uQnc6NnSQ#fi_YZT3x|Bo-3qCTI_ni5><1@=JUs@XNbOqs z!M2`|?EUDLx%Ui%$K_Mg;lFf%lm+3yn{eDE1q*TyGSz_c5fb}2gz%+n2z;Mb0(>ky zs`QAi`-)L(O&DLzy^-9e9AfvEC{~UwK53TF_<{6mNx|~?gCGM}*!aLhE82I^L?@{V zXe8ws>*NeW{K-@JsCw)t4Crcb$=c!FwYLP?J9GY@Pv+!YsPVD#jnsky2vL;-7myfU zrD>2BA8iA+nlOwt8jGEudrH`&75@1SXYQ)`K@uop$?ll<`$4S?{$?cRN<^Mp$Sj4K|`H(bn4OzlHUf{2@sM|U;Y4LTEP~WOTIJfY&-q{ z8HcGwVOGj-Tz9ZHymhEb=|Ujj(^oodVR1Dd*d18fT%xx&43ja8U0dR*S+a%CdPUer zvGJ0e;F1vPUIe^L#_(cK0ndDx%blEh6GrZE&b?15%al-@IRXD6IoM$2{UI;y=K5aZ zMB^AXP;yo7;6tAeMQbKOtkJt8+W~V>@c<#$w?aj66Yr@$e61l);gOg?jd)~52|`@Zm^Sm@W!j#2S}R;hZ6nD z)^OV-6PaTNV}K<~@#K^sXJXDiPwiX^EXL)D99(L5)*|&wUxg2!I`a`Q;n8g+-&nM- zG%|W>JBfLE(HtA(uE{8;q|f_Uca^b+VO&Bzx&x_`Q&766@hWrE3Ob8*krN>+Elo9H zQxetTdSFvYEZoj|5W<2IeDyik>L0fK@Kk_+8{pL&p1=cZEdv_3j%cfNN$s^TQhq>h z9cO94w)B2`RGvY?70|k*cKQbKy@=rJ-^v7_v1fDAwC=<26dEUt%~G6XUW>biyo|p< z43T^gYZw~;lfO~OKi!RnBU)LW^e(_1a%2dW$Ud7Fqc+P!?HXjrau_${J}inHev^i2 zd1##-)cJbC`l-6dhbHAu;-~R1`?4H;!Z!8&prCWgfJ>VjuWe5uN75TF-N{xsz)Hfm zEk1ExbJD78*|mOx((L85eqWzQ&s)#Qb_vD0m5}5X8w8Ev!h3*h6xF^RoK}HM#ZLHA zN9FVtA@Up_V&5q5C|Bg8Zej~fX3&-2o5X>2RcL^y++?Qri1=Ma!rc@h#a-b7)-r`$ z?$wErYTYzN^Y|Ryk!~L{juhn!+lqi|^(3#MLJ$Q`V|e3>u%_m+D~o&2wdNXF4cGKP zB!m^G!c|9&oVM3^DuLtZ8EAZmd>Or-(*)`Bkd=7v57e)qqEe>{g%Rpk$B9mkDkg~1LIN1Eg7r~9ZWF?pHe{veOUJxOV-lswmH?GwoQAQi$ zmB=#3GY@PNhnB`Y7%Y#{8z#7h<<;Gl8O@!ND5l7#wkRh z!#Fg`QEy`tU+P)4c~ohjpD1lXdMXphMff?aRm8 zZ=tOUc=$gspYzfd8LDTAjwV#r^@bMr=sJ0D>B6j#Ji*?(xd*W+W8+j{)y(C`6t>l zNb(0rmG(CDE|mE<^^LdS1rYcH#8n4Z{tWyHKDws4^txc_2WZU!LHk7w-}%6n_u{`N zH2HhB zpOT(9TSo8;x!|n)g92~0i9U;_CM7p7UtL$$Auv0LQM|lKmJsRSsj2uIO=2&0jSfs( z`{?P4H5Y;v?$5f`tlY$Pk{dzP|B zf26Z6H}-vRmWjGG!Edqa)7Z;T{$XvqgLM&ETZ(J|yM<|z(5=kpki{_|U|PK)PBHaj z3Q{AG#yEnETG&RX)>Pq5Y&IJbC9i1ibtU#RbZTo_bF#z0^dJ&AavaX`GJ6u#Rh?=HvE~A*q<|Kl!?4H&|uBr7Yka+MrwXN3gM3WVq7>a+@ z|731EYT-IcIcR8SXMtL7*|XLo6GMDN4@VgI$Q#mD4Qq-4xFotKI2wER*3$rUc)_nj z1@CYuTASTsv*muHaWuXH$(!0&dM-UVN~V8U;h$=g0fHBZVZOQV)L75`LE@@aKt?S) zTx6!Y5^Bp?jDFv1_-Wkm^j){+0H4)GchwWLkqn!{Zt}U+MqdPJAe3*JFo=^1(Jp|w z{d_CB^35&ys))6tQ&UG|>gaA*=@>EZGs0YLo*n1oKtnsK?kzP2He;+cHjJnCM(Ap& z>{NW7M?O)oDc-H=^GKc;PJDcE>88Q>O^OC?Lk7Q1g3}JeTKd5CTX{Od>XbK2;7PKc zrI*1&t*Uy3hFu@fUu{Ug&F9m5Xy+_~H@~m%l4p+ht{2R;5TPZR5oy3cV8pIMYfDkU z;A!Su)tYukekJlLrYtY+4&#d4d(Q@WW^U95fUEGJ&A0Z4#_e8J@ocWQjc+_1mPwR( zn@}t)Y^lf3Jyp835F3J)j1(NE4 zq{aJ1qPLNHcEmQom56kYoq%|}LVHnrTCtN1S!b#k57Z2+i)h@L2_4evKbAtJ9>sHd@!b>gQ$Po$n z@va$5^OGn<;y@c&+}RpKAri`f*p8brStsqhuE$q%78$c0y#WHSJbR0I$v zZ!I<*MwFJ7o!>L+o=`)tJWcgY!FZ8{yBd~LJ4{v%;Eke@%043}WA^wSttf7Wn0^#* z>7wH+Dftie>ZM7Zr_1CV+S_hjl%NViDsx|Z8CqH{AG;G5G3XcO^YCXf%+I2vQ>I{D zNGWWu4lTSZNl3z(TDQA3Chjb^RVw^mSGI8L+DKbFVUfHSBYP)p2!bXgTWvgh-s2D{ zQ&V+%r{U#veg{Q6Kfg7}7l1T7J}-n}ShLMFi)Ccs>CP%e0b!&=H|8(90TgO;( zn}mv;4}j8yq3(Ovj4&?>=lSt7=erh@nlwMFgL6i!S7(Z?6E-VJBe!z>pPs`G)|DtZ zmFEybBtd+9)Duu)5~br}4VAQ~%Vzz|MI+0nV?5|dpGY}Cyrjs*>cUK}b~Wue>arIF z8*qkZhs-_Kggk{va|$ePL>H^9<(b%krTT|P@McwRWvtBy_io6%WqTP0mmO9RcRMGW zl3h2oX60MslIRYD1m6Q%j+aB(`6!$XLpDh9 zy};Wk58eDu=G;a|X4f1|%<24Grwt{c2^ea_Avq*Ell6FTxqcW~8(f>_&>TE9eDMRs zb+vrTpYptOib!ZROGNE07*@{0SWCFiWc)H&&!qro$4k2(Xa z3IY9aySMg_Xj1yW_mQk~_2^tht2Ov`z)mlfzE)pb;wd;~?-W6ZwI1qI4xrleQ@}~{ zD)`QNtdqX^STHIK#A_}rNqN>HvFg_aif2jD={@jC<$1Yb|AxRQ*{HGJ!cOG$US!2% zc#bYJ;wO{oUty1$^(Rr953ItA{2t+}wEkbk6#pV@{&#)$CuQ`nO6e~Tcy8)N7Hl@a zVB&kNv_qa#&T6=A=<=y701EGGM+1y1v?oCF%b!VEs>a&W8H2K>yLi86T|o}Q@1pkP zZ}ANQCAFB2zk;sW4Zak_?c*OY#Z^0(Pnp18=i3-CZ-xn!z{58S)}KiZdfrQ15Z;YW zmv8aV7Bi-ycTC&yYis3Oe2fuQn|V1z602xPZR&t7z4~d?uu;n-qm0=7mb1Qbf=Av{ z@D=j`Lh$3fWVm-56((J-4CuDq4UfUx`yb{sQ?x@9)znLx-W=j41PgO?$5+sT(6cW} zb-SJMa;4GkrWnbOKImH2;Dc-!WR#b(*{FP)mqb~^a*u?SBOM(IR6WW zC#;+dSS*yE4-|KK(MwWAH_+RQpnu%mr0>W!?|#Fdi|zLz*|>q@To-;pYX=Rjw91Jk zN9dsV%-ls-H5r>w+52q;#1O>&wTh5BHGAUcHv0u}$#5yONMo0|NoyBNP}u5=Ju*6~ z@uNj8TxG^Er2au>u6|A-lRb$^CzKSm?hEd)Eu~Md(1yYZRIv(K;H8rNA3drksnWfQ z%(-%&Kftf8O0u)#YJ6pFr4P3*!i_Ng)bbqe1sOm3^PDkQGtNDW$yBS$?)0AF8w_MM z%|;G6$L_M&+smjUVFTb@6ovfjyGTm*7&qqwxASE~X;#tf%u9o+nwC?Kx`&-)QgK9h z0?1nR*2sqr>T^FpT?FaXb*W$E4NUC5p)UJva6m; z=`m)(x3N$vIoq!?xmusHV&xWk`BQp9aIq?UNa~*uk!Y%?%dQzccl*6w<4g_SO#T41 z*IWHd;JGa)QccaOsj##{*Jv%7^|9549=|N+341x}=tJ_819~MmELA%#AE0P0@xKbT z$^CZu?kcEfZA^}*AKI9(gtQuU@Rgt|WGwvpo3P28Us_TS(Gt)Zle#=VaJmD7)^)H9x^0#Qs!wb++hEG=8wUJ+XB=-$0Uy173 zAxEr3&1b4kQh-uC`0!51%EJCky<9y{B`}JczV4yumJ)&~YTuJc?>Ca#^AX_juS{*Q|uj zM=`-u72snz5;yJ$Rvv+VHiPZ`aokmWa+g*e3lmm+&F+HIP@3Ev=I`d}cYW(BY=zqg z%mE-O^3Qq?7bC0n)*J!L@#*t>NBSaR-95m)IM-+y<4{u@+5nwCN5Y)fl5%$pAg^9* z3dLUbdtvaupy^}DCa?BQyd1qvjJoa5Svf;BD>=@GRN-|Gj+ZT$sOVQYzpjKo$rO3`o4 zwjd>TAPZf(bbTs9AU)-iWRGP)-;w;P%E65Q4CC;WO7iI5yyU8^Np=}7_#4|2_0)R3 zD-E=+Q3VQSp^7F{B*M;r_|=CfZ+lqU0~vgAWg@4l6gEZg-&PT(q!!YmE`E)?^+1dk zu5IxQgu#`!>Z!7>b)1_}s54iSed*lK6iM1jPbH`yuXj!o?fZPhLggc|fXLpBTc|+R z=bB^0&(G!TTncvaFCFA87#Fo5l#+O(Ei}(~C)oP=m{2h78hrvw1#zt}Lm~P=?P)yU zlq+*U#yk?mW)kvIlAsR(lLy^)A^Cf?!W1y=@~6bpHwVxKhcB+eC~`8T%ud>h#Ol;I zvU*TZH0A6rbmJFRZ=T`DDpWynIUSyqddFB9lESOk+Qu*zS%p9)YsfM zk~Ki`eWYedMNMTCcW9P^H#-C0i;&PhrPS;wIJ{~rRB+s-3z?QekrZx8wH>=YX_M$a zLImGny^xzvbjVcq6K!t=iC^qh;9lL{d+5GUcpUquBk1phvnV9NBxOZzzNh^Fy$C8} zy#XL6AFpqc@eM)0;zV>Kq%u1rUYHWBgZC#tKpttw+3a*V*Iq3mN71k+9<9sdmjEL3 z81#z%z3x%?E#RQxPtJPTdw=TH;f)=n8+W@7yB1lM`t?7jBV@*H!T^eSi~N-W0Iz#^ zEz{o7!To2%|IFh*_3g>JTE4%4nf&%0dMDOz=*!V{b|?ozgO$o(5?>Q({25CGK@KkO zqHbGn@r{0Q>cIy}RA5W{rxF!+R@Ld7{n+e{|L==X9e1D_rEVC9b&@B6A0Sa&bHuJoTI-(#oplk)TU40o-i-1ep^SWCzHS}$$NS7KI60F8 z0d){1#Ly3~+xv~5aY(wbZG;hoTnNu| z`KE89YNqE#TldN3)Q?ML&$EO-OJKP!*;2>TJ_xYgi0#)h6bOHqtb=}*vvDz3 zl0os7lsq@)Qyh3fkATzrYNH9KNNa9)46G`?GOtw~rI8&*Ft?g~Ef*bmT81){$-aKu);>L zU(kg|A;~#v)kJTE*n^s`uWtsQuvZjh^YOey<5vCaMsri>L5(|c<7Tb@+iW_r1#zFY zLCn(bFkAH`5=3}`E*+|g^odgD)*3DpMyKhq(V=lml`Y2)J8M>jsY?D;wA2UG47jI<~yE)Sgq?wq>k{$OZm_Bq!7Wd!CY72 z-q#J#&svLG-KIF5rWUpX1~pQGAK)Zy>qOO}p6HQj3XYT%YtN0QYlLF~uHzPsn)TUr zA784o(ipjlKl-479Rv>*)&Lk!@>D{HsRZEK)l%AeVZ|+r_%3@9Qg!ism2+ZAAw(W` z-J63OETajGrwPiA^%{IrHRVe z0TIZGsxxkC);tk>lX0-6ETQtcfCQ-*m4GC|9-YxGC=Gb=f3eZs8(5D0NMGRkm|6EV zH~+^^TuGlyRAk$kA{rKpFm3z3K6!2Ehn+#{kZL}A?BA413!Sp&BHn@ZQw>{y*#WkY zOGwregH$~PoYSNE=y9Jg-ym-INAHfipbhK0wZasWoC%xIuqEXxSrc_!!dV&Yjt!E& zMWn*Pm3YPT8mfY2E%PBljSE9ehykMyJYooITr&3qzsBT^`=!coein7Z(?o2y(-~ zhlJ1hVj`;8l;2_;enCqIJ$kjASo1Nv5WxXau ziUdl`6GQGu8kFVZGtNu0u`zi=mr=VoD<<(o@o(8J{=aVw;RVrU|4e!NTciKGK7;!W zLkgy{|Ay92w~i~z`kNC@o*TJr7j9(Af!cO&R}xO+pa2SzLbiSi zApJ7bN#h^n#2R0H>_Wr)#yQK=V69#e0oMy}yFrH3_w9Xr@gncU=XXn&I=N2z$Tald zC*o-imTL4_F9a_FNeATwD+PH)>KzH^Hlkw{#?wm}@5#_!!8*2f)q`gGjKdb#u$tmK z8bgd?Hp+Mrwh{cPVvj!tKdV<;ok)}nTm7urcsKOnq-H*3WBn27J!9si4GWV~2~F3g z;4#b&V;@0rUi#07t!o)@8lUCA1w}YAr~QAH-Q_O;KAF=h+>y zB%3rN4UZ)q);HurFCO-SZN^r9KsUziz3zsPv$l2X&`!?y(@{Tcd7J4&HuiPD$Dt;}T4F z(_!2!GbrL$tE)dc{tMWD!0BH6(P{p>|NU?JI12$%)+p`Y3@I{!hOpDG4dLJUIBWm8 zwL-+2F zTgU(tF+*8^K+5a&9Zn@(OWxjj-7$UJ`uQnq`RLaB=8x=O{-q8TK*Ga*F=C-$SUq6P zIn*6!V9y>VvlDa{j@6krGfeH~+?w0^`Br1`$Ur8OVx@qojl^O4QJ8~vT$)qYz zJ?8t+qL7639--Q45#)DdXT9-syAUGbnFNo;Xq+=m1qm7NWa-8glw_O1xPa|klHRn2 zEjQlf16^M3JrnOTR1A5x_mK9TVYiEtoc3ZhfmuJ|bUn2-`^*ZyZlJ#zJw45Wo z>{eMZNgupyuKRlTt>l0<_L&Wh-}Blt9L!GN6qeyGU2252I?Zt& z336FM^0k&qCKs#E=I#@8mP7-{#8^HOqB`d~#5{dsSZcP@f>=>r9|p0pVWq||^WsU_ zq+HN?qJ+)gOGMA`#1Mp<(#r%#0!wjNBh^$X9|!bIMa1fg7iOiK70`g)O)3kgchvUn zA39~|2ttwJZL3il2r#FnX>=mh~|BmfgeaSZng zngJSeR^$7U`;4v8t@|e3gM~(qcB=~y$J<7}^HC2w4SrYs-1z|D+j|Yje+{wv?wpJt zXJ}4X5q!rr2sO;JLe|#U1+-TGv~v4j(XXife{jCPtM>j?_5FW%{JY|CmfwrR8~&y^ zoTd7&#Nj2s7l$kVixTL+{Tmt+WrPzgL~}s)yk_vCw0SJUAc@KW95`#9BniO>4)NiP z{VUS0Q&6AHtL7==+GCX>N0Wq7W`jl)wh!kaWa)&eK`){tP5 zrHN{r9~1ZYLpHRV;`#=+C!6Q0(J2dTOKZVHu@R#LrnWtX&$Ifel8q{i9#O$Z_r6w% zf*p0@ooFm+>0U)0?kd(sQnN|fudr+_%!Vsj&6&CEP9t=<1@$5eT45yafehbT$6 zW4mWqnprPr+JymZs>W50@AqpB-=+>z)=7jeaVD;DT0TVoaA5E}fV9UvXF2c(X!T+2 z1v!rS=`MFa!aL0ctxr!A5*DKem=NroKmh`x{R^(c7;?As=NMJPUk>ui_(iY|oWyOu z-wuAN?)zTUUy405Kg?v`O)ZLRtHb?NYaLZ}Ydf-MaXM@jI+;Db_T}6nS2N2bT0CMu zc12?A+M+=e^5(zz8Ug~e%Xj-UG|r7)0K&gIQW&&)*yQ$F#C(jY>@df<9K)EQBNI2( zL=tqQo3?4pXOQmSOB{-Mr+GYdle78x-Se8lSM6D;$f!LcO+`e~#*h3$zooDH+HsdtsWV zQUSa_mprpGf*}`njlw6VhMrx$kGc2j;UoC%WQ1TRDc!hTGakxcY`*W<#PR{wjq)tJ zN~v?J%>7!qTLG%%eAl7~DKiMDA-iTUs^*D1Ij6h@vr82=2}2vl61z=nm53IF+P;Om ztn?n``kh$D9k0ELuL@fFQ%*wi`(HG4n-eB$h(A%r7=|WJ5x@t~5$H7%oSi*{w_91u zo?1Ua56zSy(WuSKe>rW=!dgy9a#b?&!!Vt-9y8dT2Xy$XD6H^+@p&V}#hqDv? zi{*(}XBD)i;!g9aEn`KRWcsXaMW4ic2fXbb{On}R>;YxsZ*C+1GBNL0i6;R+2m7D= z`Hge<7mnZVz@nr6?NtFden;*7h9f#FFS?Ob*S^pAE1*y{6+jI8|ME@p)A3u$B`)9f z57>pc9)DP!q8p~CmX~@6plEmPIN4{Ek}1O(>f^B4tILE$rVQ~>1yBiv9oQuXG+7<( zk8K^jT@?C$LInBE9%3r-tmFIP_) z0iNG|(S!I28)@-OIdB6Zj*NZlWf|SBK_bayvqty(L24g2kk!J1+`kg*9B3s_k1|wM zv_yB+mgRL9$=e8*SP15N@~=Sbayq4-G#(Okbq5>2U*V;hnJ%{=64dCfwyWv7h;FBd zUD}=Xj=~3p4%XocVk7B^A^4)b^Cx1qrq5c$UJyX0YHt@HxKvnln65wPdK4y^f$v{t z^S#96Og433NhWUpYulP4J_TDW&wAL5@VOK1s1>tb9M)r!@)0yZvdp?N}L zfCTNtp|(0hMrP_w$u{<;cElppjynf(AhN6&WdQF@uhO2BY2WHS=tQE-q0dCgA@kPU z-f8izOU$(^m0pj-atTY$$`$MR)BJfrYUy-ZS*fLoq#kX~p@&T6w81_~xbDk0EGI6c zt8`Mc=^y^dhBKd;a}Tl}wuIuM8YM%E(3(KZP7vy<0uc5!hRE?bWogE(Y67Wb_u>uR zBT2iE%JBunW~qaze8qSr>>oa#Fm_b94T=q2o<5R=!F>_=P%_^>1tXIazu-L>k|SM< zA6i|HG*aDsj8iZ9UdvqxZN(j2vTd>W3#Z=|;PeyGq*7rqleI+_>(QI=&IT;Z`@ySg zxPsm^ zENG5Z5$^)|D1|eNKF)AEmKip~K%GVT-iSTA^(@^9#DfY6fPcvExtPbhmwL5UA9EFB zmG^>XqyVjLY+SCg-uHC#U=6a7X8X9SFTdE9-~X-hsc1L<`kGU2#wrBZfEc>xYkMZH z4rmBfw;G?eAuir6GY6=3r*M4Po;}~X9Fi(l(*-SXf;_9tQA`u^bm)8X!S#6Dk%;p$-)r6cz&&$D1* zsjpH_XeZo`Aw%>5rvyC6k?dY3r|x*te=)WMY_~0_QJreE{(h{a0`mz#Os$X>65FbZ z>*bEa_Z{e!Z>ei^4LRv4B3OJlJSZ&dvsv*}N&sqv$tFE^4506&uJ2w?vRY}3xi=cc zN{20fj!b16Vsi_VX(!y~{F%IIiF|PHrI`?QMTByNhvu$6=~QHYo8x=FhBfT-0kxth z-HK1Y8nqV1damxvxQEbvQbF+1f$VJoTC#IgN&Bb3+UK~DpF~|k_jxHWAqZ!hPu@OH zmPf&_Ozc0Tu93FUIg)Rzi9k*_rAZ1~a z$DU=@!Bgk;5Qrz_c46xNi5j}I%|o?C*Y{Q|r-v8Lb!i9q_#xk_hVCB7C_jc1EBAlP zos8;K)SuJ0^bGbjUa~?{BgsNSTn28S+CPBzHqskT#PMduTtRZ)OGESYuOZg|0J{HQ z1au3lYJy*vV-|-PijR!Fl9ZvY!ts8jXb~!p1I8M(tI8VrCM(OPN*f? zg_F5fdd1~k$cjJpyY}^#DrC7L`(S+Eo9e75M-Eh7!r0-u5z>jZ8M)F{+0`-oAE*a$ z))_ozmPz?bF?t!_UK+gNrti5kGR1why+#@v z;3z9+O)q%xYUv?9Ik-l2=<404MCF)zDgi1X*P~FewObixMNN0c`fM|6V^^uz68wmH zQtgBe`o+_bT3%XSgz4;QDzB-LAE4CMz^x)V);+H)A~!RZf>qTCt^zJbZFi-yjl@~z zys*K(c?K#0me&CF;(pyeo4m{9r|OJy03|+6rgefd9*+PBZmft=rVSIuWH)BXejvGF zY``Dw6DUZ#&MeTwjnBic#&`ktD0ni8FeC5+Rggpaqu>30*orFQD)|$0e5>?@(KR&l zlS8Y}k(`HFIW#rZc1W^=g|09& zmn`AfL23>TOZu1U=k3^HMi+Mp^xU0BH5%C`V z&$Na_2=7?!^dT-dRm|m~F)F8Dt_u$_xmUSo0;Jd85pL(YmeeOt~ylC_W!IWVbG=bC5YGT^yJa;_ycz~nUre-gCPJSD6 z@xeg`dy~4Pcl49C&$OIY&t_r=5Q?~f$*vESN}AkBx6+IqOjqwsAgmO( zTF!mtkRqF&XH>&&k8I%_n$Av-&EB6Mon05f7`>RkizWivLMsuWrn}ijNY?za>w9f7 z)dF3DSf0_4x_?mIdQ2+P5x&n%1@lqSy+Ti0)!G*OqJlg6QQx92g{4%9t8*Zo$&%6p zU6!6b>UsS~YTGW;3eyX`NPrVk#CrEg{y6Iv1&GW{SB`_h=Upj2=*h?>@OYXJzDPA1 zrKw(Z(W`0<5b`FZX=WVdOcCB4n8}XS=+WAYQ0oH;_ks_meQs1;?)|g9zAy~_0Ktvl z(ZM>#M84q~1KFHAFx<|-cFAVx3F~1q7yXl{47u@|@rjk<@1d{cv3H7@xgG`xOvG2$ z%43&}m1){d}n9WSyUUu+f+YzY%{ZNkvCGzCRHo>5Q$6mFE3c( zcjxX{$p}!CSvtH4#tn(3>8`QBG#7qY)6#fGG0BA{{7@R(LQ|J^Fj;(7w0qr@ERB(s zJg`Vr7<0U|wbrAb<i~kP8qX+kEp;)=PJ6XFfv{hRKN7Dx){Sg~YTT zV`+G&)s|r;ne@Nxg~c_-ZN9UDUfJ2Lf4o_H|x~ zEo7*Xtb`;+|NTD`tW|zcUJlV_@8s_M97~WKf&X*Wy!l*BbMYx;Tus6rkDhuCAL7|! zMhl9dek|RO5S_q@@whX6Sx1*U15%)~M6EFB;7W>o2ss6l9r2cXZWIqy^D6>aox*96|2RcLa6tSqA|NoY=Hpi<;c zgizrZX9a%);edFoYe3XGDgkgN^UnalDK!{K2vTYRe)DYQ7wm=IzIXHv9u9}OvEH9c zC6V8K*S+1%IU~P4xc<5&ayfsNj?@I8Qrkeyv#bR9b)-UF_Mf45DP;dO4Cp@t@c(BH zTK_W#z>@mk@I440l2TDNW*TS%d5Yz|3$7<%lD_1e`aoi5I)MISM!GQip-*RR-``VEjUp0RQ|mE4O!EHkj;e6(ayNK{QTpQgXEoP)%JZ!l)wOXN zfP7n7e}H-!7=zPrXXk~w26LM1(1wbLeWj)$y_<6S8;jApuBqI~%5yQT9l*8h&=p?b zTX^MZ>QKgLeu`CoH}Md(eqLBL>Lpxyp@OX`THY4b&ve3>9cS`5;|1#_F|AN9?#N_H zSl3}`CXL`d$y-R!>LqyxfjfB%{AaEaHKH=RE~ zh)2L>=EI8zjoxzC`~ZmwVBFyY(?OQ?yAi$rxgjd*n_yq+D_Ys4k9$c9n2_Fb)Z6)H zCu6?76q1lB)E+d|Glsr|BucM^@O2!zC?TwuGhwWX;{UrY?~m>$2lblwPA1jOl9LB)?_l&kw^@~RO}{H=I6BDkKWMTl*n&-O}3U@ zIjc^810E6pbWRLIp2%(;GoIuk4*ob{oult!d5RtT=0kxG4mDac3cBtQ84`T}}&9WQ_0VaYA3j>OcrQl=l$EEy zE{${AhSPfzfZ3)BDALO40A|~3>`xvt@83YGYe>9W?cRN}m9bhq;0NxZLZd4zuL21U zH>OZq%(!gCdOK*=w8n1$l1y1I6=#d;+P9QPc%)+ld**I?rBHD(0r2Thi|@VEJw-Y- zQZ`FHZrx>!!>Oq3GpNGz3(4nhyzUV>frkt#P_qW*wiM*b5K||{CiiusmO!u&+{hEN zYwFd<$RF=SS>WBIX1FkP22xFM5gG;T%!H8OMr2{Ts(m)9RuMP4~VW9G{3 zsYj+EgVy38f*I9mxT?2I-)E-~dm%P+++zUN!zDyptSZos4CIRSs`7pThi)wV=5Ya; z&VrS$n2O_~Kqvp}Bd(P5f`rSXSWnFn=jAGA^$qInLHS(Xth(4hd|;nLs$;$-kisZ| z1MVxo&y`{6cpdVs)L9B@;jgMF<0NE@{?ImVO>U|ct=vzxxx6;aB8h?}ix%MDB2`^Sb#HVTdg1L0~Y9m|vA_v;BpUwB{kF!wSy&C}9X}mS}s<~G9 z)6`=ec#6P$6TM&$f&D?Z!hKmDU|;i29@wz;wO$p9T4?mqoY2gpuFTAz{{WRnkDre) zQHXrM2iTH1Sd&8NuBGP|{RcTRtD0s{&kO}3>cDE=oqpbX$!?Qnm^^XWkS=y#JS!HK}WBX;cxh{v)>Y6H8 zW4IiP{*s661et*5d0-8~q3hAk<8_((l_8JU!}$10U!8RdTTx6{VXJ2uX$FVBJHQ|_ zG=gWPrx9;lb?~WMdElUNqiDv@|B9)GQTzJk`qowFIV59%mcRu@x8V7-;@A^|4?6-aa_WZbjf&W8N{6B-J`?r0-jdzZ|_P~Rllz<*x$#d!I zy0BPVk@SCdZ~g7ReiqFMS5;e>S^DJmt$WciXH~E6yYco}WHh&twUEdhhE<+wyMS%F z*QhJy|1)4+D$kF+RGw|m?SoNU*DYNTol(xF|CZZ2G2L{sjLF1BZ}`MlYb&r!yfDc+ z-23l@{|tAp?Ehf*8rUETw5WC!oA2mW)4OcfTvbuv#WE@O-%IuX@bCK1@OVl+5@+iC zt55G-zP;|ar)zQjP5!@ky@B3)xBtgec@$3g^n!1%H(m;ix&O`iKSOyCFvXdVQYUZW)g zxP%`q8Aedaa7+}~EJs?>81nHRu;=z8@3mXY(Z37JvvMA64F0?%Z#TE#)zE-RoDU|j zS81*GjMZ1lR8RYJUhM~PAB{ZcKVW0e^kATCvTX0t9f7W*E`zRrN@0IlHovj{@za0% PAG(T!`4_ux{C^Vwkj2P{ diff --git a/apiconcepts/filetypesupport/imarkupdatavisitor.md b/apiconcepts/filetypesupport/imarkupdatavisitor.md index 009c580016..d43a28d158 100644 --- a/apiconcepts/filetypesupport/imarkupdatavisitor.md +++ b/apiconcepts/filetypesupport/imarkupdatavisitor.md @@ -1,18 +1,15 @@ -IMarkupDataVisitor -=== +# IMarkupDataVisitor -The visitor pattern allows a class implementer to traverse all the child objects in an objects hierarchy without having to know how the hierarchy is implemented or having to be aware of any changes in how the hierarchy is implemented. +The visitor pattern lets you traverse all child objects in a markup hierarchy without depending on the hierarchy's internal implementation. This makes your code easier to maintain when the hierarchy changes. -Implementing IMarkupDataVisitor --- +## Implementing `IMarkupDataVisitor` -All that is required is that your class needs to derive from the [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) interface and to explicitly implement all the interface’s methods. To use the visitor pattern it is normally helpful to write the similar private method that calls accept visitor for all the markup data child items of the given parent. +To use this pattern, implement the [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) interface and provide all required visitor methods. In most cases, it also helps to add a private helper method that calls `AcceptVisitor()` for each child item in a markup container. # [C#](#tab/tabid-1) ```cs private void AppendItems(IAbstractMarkupDataContainer parent) { - // implemented as a visitor foreach (var item in parent) { item.AcceptVisitor(this); @@ -21,52 +18,47 @@ private void AppendItems(IAbstractMarkupDataContainer parent) ``` *** -This method can then be used to kick off the traversal of all the items in a paragraph-unit so that they can be written to the translated target document. This can be done in the implementation of [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) where the passed [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) object can have its Source and Target paragraphs passed to ```AppendItems()``` and the implementations of the [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) interface methods can process the various types of text and mark-up objects that form part of the paragraph data hierarchies. +You can use this helper method to start traversal for all items in a paragraph unit so that your writer can output them to the translated target document. A common place to do this is in [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentHandler.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentHandler_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_). There, the [IParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml) object can pass its source and target paragraphs to `AppendItems()`, while the `IMarkupDataVisitor` methods process the different text and markup objects in the hierarchy. -**VisitTagPair()** +## Visitor methods -[VisitTagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitTagPair_Sdl_FileTypeSupport_Framework_BilingualApi_ITagPair_) method is called when a tag pair object of type [ITagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ITagPair.yml) is being visited. This tag pair object is normally processed by writing to the target document the tag pair start tag then processing all the tag pair’s child nodes then writing the tag pair end tag. However, some Bilingual Writers may need to cache this information first. In order to process all the child nodes of a tag pair the ```AppendItems()``` private helper method can be called with the tag object as the parameter. +### `VisitTagPair()` -**VisitPlaceholderTag()** +[VisitTagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitTagPair_Sdl_FileTypeSupport_Framework_BilingualApi_ITagPair_) is called when the visitor reaches an [ITagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ITagPair.yml) object. A typical implementation writes the start tag to the target document, processes the child nodes, and then writes the end tag. Some bilingual writers may need to cache this information first. To process the child nodes, call `AppendItems()` with the tag pair as the parameter. -[VisitPlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitPlaceholderTag_Sdl_FileTypeSupport_Framework_BilingualApi_IPlaceholderTag_) method is called when a placeholder tag object of type [IPlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IPlaceholderTag.yml) is being visited. This placeholder object is normally processed by writing to the target document this placeholder tag. However, some Bilingual writers may need to cache this information first. +### `VisitPlaceholderTag()` -**VisitText()** +[VisitPlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitPlaceholderTag_Sdl_FileTypeSupport_Framework_BilingualApi_IPlaceholderTag_) is called when the visitor reaches an [IPlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IPlaceholderTag.yml) object. A typical implementation writes the placeholder tag to the target document, although some bilingual writers may need to cache the information first. -[VisitText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitText_Sdl_FileTypeSupport_Framework_BilingualApi_IText_) method is called when a text object of type [IText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IText.yml) is being visited. This text object is normally processed by writing the content of the text object to the target document. However, when processing text items it may be necessary to consider the value of [ContentRestriction](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContentRestriction.yml) as the content restriction type may indicate that the source text is to be written instead of the target text. If this is the case then when a translatable paragraph-unit is being processed then ```AppendItems()``` should be called for the source paragraph rather than then target paragraph ensuring that subsequent calls to [VisitText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitText_Sdl_FileTypeSupport_Framework_BilingualApi_IText_) will be for the source text. +### `VisitText()` -**VisitSegment()** +[VisitText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitText_Sdl_FileTypeSupport_Framework_BilingualApi_IText_) is called when the visitor reaches an [IText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IText.yml) object. A typical implementation writes the text content to the target document. When you process text items, also consider the [ContentRestriction](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContentRestriction.yml) value. In some cases, the restriction indicates that you should write the source text instead of the target text. When that happens for a translatable paragraph unit, call `AppendItems()` for the source paragraph instead of the target paragraph so that later calls to `VisitText()` use the source text. -[VisitSegment](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitSegment_Sdl_FileTypeSupport_Framework_BilingualApi_ISegment_) method is called when a segment object of type ISegment is being visited. This segment object is normally processed by writing any required information from the [ISegmentPairProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISegmentPairProperties.yml) , such as [MatchPercent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ITranslationOrigin.yml#Sdl_FileTypeSupport_Framework_NativeApi_ITranslationOrigin_MatchPercent) or [TranslationOrigin](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISegmentPairProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISegmentPairProperties_TranslationOrigin). +### `VisitSegment()` -**VisitLocationMarker()** +[VisitSegment](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitSegment_Sdl_FileTypeSupport_Framework_BilingualApi_ISegment_) is called when the visitor reaches an [ISegment](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ISegment.yml) object. A typical implementation writes any required information from [ISegmentPairProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISegmentPairProperties.yml), such as [MatchPercent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ITranslationOrigin.yml#Sdl_FileTypeSupport_Framework_NativeApi_ITranslationOrigin_MatchPercent) or [TranslationOrigin](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISegmentPairProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISegmentPairProperties_TranslationOrigin). -[VisitLocationMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitLocationMarker_Sdl_FileTypeSupport_Framework_BilingualApi_ILocationMarker_) method is called when a location marker object of type [ILocationMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILocationMarker.yml) is being visited. Location markers are typically used for locating a position within a translated document, such as the scroll position when previewing a document within a framework based editor. +### `VisitLocationMarker()` -**VisitOtherMarker()** +[VisitLocationMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitLocationMarker_Sdl_FileTypeSupport_Framework_BilingualApi_ILocationMarker_) is called when the visitor reaches an [ILocationMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILocationMarker.yml) object. Location markers usually identify a position in a translated document, such as the scroll position in a framework-based preview editor. -[VisitOtherMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitOtherMarker_Sdl_FileTypeSupport_Framework_BilingualApi_IOtherMarker_) method is called when an alternate location marker object of type [IOtherMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IOtherMarker.yml) is being visited. +### `VisitOtherMarker()` -**VisitRevisionMarker()** +[VisitOtherMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitOtherMarker_Sdl_FileTypeSupport_Framework_BilingualApi_IOtherMarker_) is called when the visitor reaches an [IOtherMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IOtherMarker.yml) object. -[VisitRevisionMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitRevisionMarker_Sdl_FileTypeSupport_Framework_BilingualApi_IRevisionMarker_) method is called when an track change location marker object of type [IRevisionMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IRevisionMarker.yml) is being visited. +### `VisitRevisionMarker()` -**VisitLockedContent()** +[VisitRevisionMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitRevisionMarker_Sdl_FileTypeSupport_Framework_BilingualApi_IRevisionMarker_) is called when the visitor reaches an [IRevisionMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IRevisionMarker.yml) object. Revision markers usually represent tracked changes. -[VisitLockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitLockedContent_Sdl_FileTypeSupport_Framework_BilingualApi_ILockedContent_) method is called when a locked content container object of type [ILockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILockedContent.yml) is being visited. This locked content object is normally processed by checking the value of [LockType](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ILockedContentProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_ILockedContentProperties_LockType) in its Properties property. The value of this lock type may indicate how to treat the contents of this container when writing them to the translated target document. Also when processing this [ILockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILockedContent.yml) container it would normally be the case that ```AppendItems()``` would be called for its [Content](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILockedContent.yml#Sdl_FileTypeSupport_Framework_BilingualApi_ILockedContent_Content) collection of child objects. +### `VisitLockedContent()` -See Also --- +[VisitLockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitLockedContent_Sdl_FileTypeSupport_Framework_BilingualApi_ILockedContent_) is called when the visitor reaches an [ILockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILockedContent.yml) container. A typical implementation checks the [LockType](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ILockedContentProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_ILockedContentProperties_LockType) value in the container's properties to determine how to handle the content when writing the translated target document. In many cases, you then call `AppendItems()` for the [Content](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILockedContent.yml#Sdl_FileTypeSupport_Framework_BilingualApi_ILockedContent_Content) collection. -**Reference** +## See also -[IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) - - - -[Visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern) - -[Design patterns](https://en.wikipedia.org/wiki/Design_Patterns) +- Reference [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) +- [Visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern) +- [Design patterns](https://en.wikipedia.org/wiki/Design_Patterns) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/implement_the_ui_controller_class_bil.md b/apiconcepts/filetypesupport/implement_the_ui_controller_class_bil.md index 67ddd49386..b62edbf439 100644 --- a/apiconcepts/filetypesupport/implement_the_ui_controller_class_bil.md +++ b/apiconcepts/filetypesupport/implement_the_ui_controller_class_bil.md @@ -1,44 +1,43 @@ -Implement the UI Controller Class -=== +# Implement the UI Controller Class -In this chapter you will learn how to implement a class that controls the actual plug-in user interface. +Implement a class that controls the actual plug-in user interface. -When implementing control for the plug-in user interface, you basically need to cover the following scenarios: +## Settings Page Scenarios -* The user clicks the **Reset to Defaults** button, thereby restoring all control elements to their intended default settings. -* The user clicks **OK**, thereby applying (saving) the settings. -After changing the control element settings, the user goes to another settings page, which should also save any changes to the form control elements. -* The user clicks the **Cancel** button, any changes to the control settings should be discarded. +A settings page for the plug-in user interface must handle these scenarios: -A settings page does not implement its own **OK**, **Cancel**, **Reset** buttons, but will rely on the control elements that are provided by the dialog box of the framework, which is made possible through this class. +- The user clicks **Reset to Defaults**, restoring all control elements to their default settings +- The user clicks **OK**, saving the settings +- The user navigates to another settings page, which should save changes to form control elements +- The user clicks **Cancel**, discarding all changes to control settings -Below you see an example of a settings page as it is implemented for one of the default file types in Var:ProductName: +The settings page does not implement its own **OK**, **Cancel**, or **Reset** buttons. Instead, it uses the control elements provided by the framework's dialog box. + +Below is an example of a settings page as implemented for a default file type in `Var:ProductName`: ![SampleSettingsPage](images/SampleSettingsPage.jpg) -Implement the Settings Page Class --- +## Implement the Settings Page Class -Add a class called e.g. **SettingsPage.cs** to your project. This is one of the classes that is referenced from the File Type Component Builder file, which was covered in one of the previous chapters (see [Create a New File Type Component Builder](create_new_file_type_component_builder.md)), i.e. it is not the UI class itself that is referenced in the File Type Component Builder. Without this reference, the plug-in UI would not be recognized and displayed by Var:ProductName. +Add a class called, for example, **SettingsPage.cs** to your project. This class is referenced from the File Type Component Builder file (see [Create a New File Type Component Builder](create_new_file_type_component_builder.md)). It is not the UI class itself that is referenced. Without this reference, the plug-in UI would not be recognized or displayed by `Var:ProductName`. -This class acts as an intermediary between the plug-in UI (see [Implement the User Interface](implement_the_user_interface_bil.md)) and the class that is used to store and retrieve the settings to/from the settings bundle (see [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md)). +This class acts as an intermediary between the plug-in UI (see [Implement the User Interface](implement_the_user_interface_bil.md)) and the class that stores and retrieves settings to/from the settings bundle (see [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md)). -This class needs to use the following namespaces: +This class requires the following namespaces: -* **Sdl.FileTypeSupport.Framework.Core.Settings** -* **Sdl.Core.Settings** -* **Sdl.Core.PluginFramework** +- `Sdl.FileTypeSupport.Framework.Core.Settings` +- `Sdl.Core.Settings` +- `Sdl.Core.PluginFramework` -Moreover, this component needs to be derived from the ```AbstractFileTypeSettingsPage``` class, which provides the methods for setting the plug-in UI according to the values of the settings class. +This component must derive from the `AbstractFileTypeSettingsPage` class, which provides methods for setting the plug-in UI according to the settings class values. -Reset to the Default Settings --- +## Reset to Default Settings -The ```ResetToDefaults``` is triggered when the user clicks the button **Reset to Defaults** in the user interface. +The `ResetToDefaults` method is triggered when the user clicks **Reset to Defaults** in the user interface: ![reset_to_defaults](images/reset_to_defaults.jpg) -In our implementation we override this method as shown in the example below. We call the base class to make sure that the settings are reset correctly, and then make sure we update the settings accordingly: +Override this method to call the base class to ensure settings reset correctly, then update the UI: # [C#](#tab/tabid-1) ```cs @@ -48,12 +47,10 @@ public override void ResetToDefaults() Control.UpdateControl(); } ``` -*** -Reload the Settings --- +## Reload the Settings -When the user moves back to the settings page of our plug-in, we need to make certain that the plug-in UI is displayed with the most up-to-date settings from the settings bundle. This is done through the ```ReloadSettings``` method, which we override as shown below. Here, we must calll the base class to make sure that the settings are reloaded correctly before updating the UI: +When the user navigates back to the plug-in settings page, ensure the plug-in UI displays the most up-to-date settings from the settings bundle. Override the `Refresh` method to call the base class first to ensure settings reload correctly, then update the UI: # [C#](#tab/tabid-2) ```cs @@ -63,12 +60,10 @@ public override void Refresh() Control.UpdateControl(); } ``` -*** -Declare the Class in the File Type Component Builder --- +## Declare the Class in the File Type Component Builder -For the plug-in settings UI to become visible in Var:ProductName, the File Type Component Builder file needs to include the following method. You may open the **.sdlfiletype* file in a text editor, then search for <```WinFormSettingsPageIds```>, and add the node to the list of settings page IDs. +To make the plug-in settings UI visible in `Var:ProductName`, the File Type Component Builder file must include the settings page IDs. Open the **.sdlfiletype** file in a text editor, search for `WinFormSettingsPageIds`, and add the node to the list: ![excel_verifier_simplified_gui](images/excel_verifier_simplified_gui.jpg) @@ -81,12 +76,10 @@ For the plug-in settings UI to become visible in Var:ProductName, the File Type ``` -*** -Putting it all Together --- +## Putting It All Together -The complete class should now look as shown below: +The complete class should now look as follows: # [C#](#tab/tabid-4) ```cs @@ -100,57 +93,44 @@ using Sdl.FileTypeSupport.Framework.Core.Settings; namespace Sdk.FileTypeSupport.Samples.WordArtVerifier { /// - /// This class controls the plug-in user interface. It controls what happens, for example, - /// when the user clicks the button in the user interface for resetting the control elements - /// to their default values. This class is referenced in the file type definition. Without - /// this reference in the SDLFILETYPE file, the plug-in user interface would not be available - /// to the end user. + /// This class controls the plug-in user interface. It controls what happens when the user + /// clicks the button to reset control elements to their default values. This class is referenced + /// in the file type definition. Without this reference in the SDLFILETYPE file, the plug-in + /// user interface would not be available to the end user. /// [FileTypeSettingsPage(Id="WordArtVerifier_Settings", Name="Settings_Name", Description="Settings_Description")] class SettingsPage : AbstractFileTypeSettingsPage { /// - /// Triggered, when the user clicks the button Reset to Defaults button in - /// Trados Studio. Restores the default check box state, which should - /// be Checked (i.e. verification function enabled), and the default maximum - /// word count, which is 3. + /// Triggered when the user clicks the Reset to Defaults button in Trados Studio. + /// Restores the default check box state (verification enabled) and the default + /// maximum word count, which is 3. /// - #region "ResetToDefaults" public override void ResetToDefaults() { base.ResetToDefaults(); Control.UpdateControl(); } - #endregion /// - /// Triggered when the user raises the plug-in UI, whose controls (in this case the check box - /// and the maximum word count text field) will then be set according to the values stored in - /// the settings bundle. + /// Triggered when the user opens the plug-in UI. The controls (the check box and the + /// maximum word count text field) are set according to the values stored in the + /// settings bundle. /// - /// - #region "ReloadSettings" public override void Refresh() { base.Refresh(); Control.UpdateControl(); } - #endregion } } ``` -*** - -See Also --- - - -[Implement the User Interface](implement_the_user_interface_bil.md) +## See Also -[Loading and Saving the Settings](loading_and_saving_the_settings_bil.md) +- [Implement the User Interface](implement_the_user_interface_bil.md) +- [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/implement_the_ui_controller_class_native.md b/apiconcepts/filetypesupport/implement_the_ui_controller_class_native.md index e323dfbe44..0ff86c3211 100644 --- a/apiconcepts/filetypesupport/implement_the_ui_controller_class_native.md +++ b/apiconcepts/filetypesupport/implement_the_ui_controller_class_native.md @@ -1,51 +1,51 @@ -Implement the UI Controller Class -=== +# Implement the UI Controller Class -In this chapter you will learn how to implement a class that controls the actual plug-in user interface. +Implement a class that controls the actual plug-in user interface. -When implementing control for the plug-in user interface, you need to cover the following scenarios: +## Settings Page Scenarios -* The user clicks the **Reset to Defaults** button, thereby restoring all control elements to their intended default settings. -* The user clicks **OK**, thereby applying (saving) the settings. -* After changing the control element settings, the user goes to another settings page, which should also save any changes to the form control elements. -* The user clicks the **Cancel** button, any changes to the control settings should be discarded. +A settings page for the plug-in user interface must handle these scenarios: -A settings page does not implement its own **OK**, **Cancel**, **Reset** buttons, but will rely on the control elements that are provided by the dialog box of the framework, which is made possible through this class. -Below you see an example of a settings page as it is implemented for one of the default file types in Var:ProductName: +- The user clicks **Reset to Defaults**, restoring all control elements to their default settings +- The user clicks **OK**, saving the settings +- The user navigates to another settings page, which should save changes to form control elements +- The user clicks **Cancel**, discarding all changes to control settings + +The settings page does not implement its own **OK**, **Cancel**, or **Reset** buttons. Instead, it uses the control elements provided by the framework's dialog box. + +Below is an example of a settings page as implemented for a default file type in `Var:ProductName`: ![SampleSettingsPage](images/SampleSettingsPage.jpg) -Implement the Settings Page Class --- +## Implement the Settings Page Class -Add a class called e.g. **SettingsPage.cs** to your project. This is one of the classes that is referenced from the new File Type Component Builder that will be covered in a later chapter (see [Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md)), i.e. it is not the UI class itself that is referenced in the File Type Component Builder. Without this reference, the plug-in UI would not be recognized and displayed by Var:ProductName. +Add a class called, for example, **SettingsPage.cs** to your project. This class is referenced from the File Type Component Builder (see [Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md)). It is not the UI class itself that is referenced. Without this reference, the plug-in UI would not be recognized or displayed by `Var:ProductName`. -This class acts as an intermediary between the plug-in UI (see [Implement the User Interface](implement_the_user_interface_native.md)) and the class that is used to store and retrieve the settings to/from the settings bundle (see [Loading and Saving the Settings](loading_and_saving_the_settings_native.md)). +This class acts as an intermediary between the plug-in UI (see [Implement the User Interface](implement_the_user_interface_native.md)) and the class that stores and retrieves settings to/from the settings bundle (see [Loading and Saving the Settings](loading_and_saving_the_settings_native.md)). -This class needs to use the following namespaces: +This class requires the following namespaces: -* **Sdl.FileTypeSupport.Framework.Core.Settings** -* **Sdl.Core.Settings** -* **Sdl.Core.PluginFramework** +- `Sdl.FileTypeSupport.Framework.Core.Settings` +- `Sdl.Core.Settings` +- `Sdl.Core.PluginFramework` -Moreover, this component needs to be derived from the ```AbstractFilterDefinitionSettingsPage``` base class, which provides the methods for setting the plug-in UI according to the values of the settings bundle. -First, create two objects based on the ```VerifierSettings``` class and on the user interface (i.e. ```SettingsUI```) as shown below: +This component must derive from the `AbstractFilterDefinitionSettingsPage` base class, which provides methods for setting the plug-in UI according to the settings bundle values. + +Create two objects: one based on the `VerifierSettings` class and one for the user interface (`SettingsUI`): # [C#](#tab/tabid-1) ```cs [FileTypeSettingsPage(Id="XMLVerifier_Settings", Name="Settings_Name", Description="Settings_Description")] class SettingsPage : AbstractFileTypeSettingsPage ``` -*** -Reset to the Default Settings --- +## Reset to Default Settings -Another method provided by the base class is ```ResetToDefaults```. It is triggered when the user clicks the button **Reset to Defaults** in the user interface. +The `ResetToDefaults` method is triggered when the user clicks **Reset to Defaults** in the user interface: ![reset_to_defaults](images/reset_to_defaults.jpg) -In our implementation we override this method as shown in the example below. We call the ```ResetToDefaults``` method of the ```VerifierSettings``` class, and then update the user interface accordingly. +Override this method to call `ResetToDefaults` on the `VerifierSettings` class, then update the user interface: # [C#](#tab/tabid-2) ```cs @@ -55,12 +55,10 @@ public override void ResetToDefaults() Control.UpdateControl(); } ``` -*** -Refresh the Settings --- +## Refresh the Settings -When the user moves back to the settings page of our plug-in, we need to make certain that the plug-in UI is displayed with the most up-to-date settings from the settings bundle. This is done through the ```ReloadSettings``` method, which we override as shown below. Here, we call the base class which will populate the ```VerificationSettings``` for us. +When the user navigates back to the plug-in settings page, ensure the plug-in UI displays the most up-to-date settings from the settings bundle. Override the `Refresh` method. The base class populates the `VerificationSettings` for you: # [C#](#tab/tabid-3) ```cs @@ -70,12 +68,10 @@ public override void Refresh() Control.UpdateControl(); } ``` -*** -Putting it all Together --- +## Putting It All Together -All put together your ```SettingsPage``` class should now look like as shown below: +Your `SettingsPage` class should now look as follows: # [C#](#tab/tabid-4) ```cs @@ -86,62 +82,45 @@ using System.Text; using Sdl.Core.Settings; using Sdl.FileTypeSupport.Framework.Core.Settings; - namespace Sdk.FileTypeSupport.Samples.XMLChecker { /// - /// This class controls the plug-in user interface. It controls what happens, for example, - /// when the user clicks the button in the user interface for resetting the control elements - /// to their default values. This class is referenced in the file type definition. Without - /// this reference in the FILETPYE file, the plug-in user interface would not be available - /// to the end user. + /// This class controls the plug-in user interface. It controls what happens when the user + /// clicks the button to reset control elements to their default values. This class is referenced + /// in the file type definition. Without this reference in the FILETYPE file, the plug-in + /// user interface would not be available to the end user. /// - #region "ClassDeclaration" [FileTypeSettingsPage(Id="XMLVerifier_Settings", Name="Settings_Name", Description="Settings_Description")] class SettingsPage : AbstractFileTypeSettingsPage - #endregion { /// - /// Triggered, when the user clicks the button Reset to Defaults button in - /// Trados Studio. Restores the default check box state, which should - /// be Checked (i.e. verification function enabled). + /// Triggered when the user clicks the Reset to Defaults button in Trados Studio. + /// Restores the default check box state (verification enabled). /// - #region "ResetToDefaults" public override void ResetToDefaults() { base.ResetToDefaults(); Control.UpdateControl(); } - #endregion /// - /// Triggered when the user raises the plug-in UI, whose controls (in this case the check box) - /// will then be set according to the values stored in the settings bundle. + /// Triggered when the user opens the plug-in UI. The controls (the check box) + /// are set according to the values stored in the settings bundle. /// - /// - #region "ReloadSettings" public override void Refresh() { base.Refresh(); Control.UpdateControl(); } - #endregion } } ``` -*** - -See Also --- - - - -[Implement the User Interface](implement_the_user_interface_native.md) -[Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md) +## See Also -[Loading and Saving the Settings](loading_and_saving_the_settings_native.md) +- [Implement the User Interface](implement_the_user_interface_native.md) +- [Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md) +- [Loading and Saving the Settings](loading_and_saving_the_settings_native.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/implement_the_user_interface_bil.md b/apiconcepts/filetypesupport/implement_the_user_interface_bil.md index 9760a7f4ab..334a3de5d6 100644 --- a/apiconcepts/filetypesupport/implement_the_user_interface_bil.md +++ b/apiconcepts/filetypesupport/implement_the_user_interface_bil.md @@ -1,38 +1,36 @@ -Implement the User Interface -=== +# Implement the User Interface -In this step you will learn how to add a user interface to your plug-in, through which end users can configure the verification settings at runtime. +Add a user interface to your plug-in through which end users can configure verification settings at runtime. -Add a User Control --- +## Add a User Control -Implement the graphical user interface by adding a user control, which you can name e.g. **SettingsUI.cs**. This is the interface that users will see when configuring the file type plug-in in Var:ProductName through e.g. **File** > **Options** > **File Types**. Our simple bilingual verifier will implement two settings through with users can enable/disable the word count check and specify the maximum number of words. First, add a check box to the user control, which you call ```cb_CheckWordArt```. +Implement the graphical user interface by adding a user control, for example **SettingsUI.cs**. This is the interface users see when configuring the file type plug-in in `Var:ProductName` through **File** > **Options** > **File Types**. Our simple bilingual verifier implements two settings: -Furthermore, add a text field control element (named ```txt_MaxWordCount```) into which users can enter the maximum number of words allowed for WordArt objects at runtime. The default value should be 3. +- Enable or disable the word count check +- Specify the maximum number of words -The user control should look as shown below: +Add a check box named `cb_CheckWordArt` to the user control. Also add a text field control named `txt_MaxWordCount` where users enter the maximum number of words allowed for WordArt objects. Set the default value to 3. + +The user control should look as follows: ![excel_verifier_simplified_gui](images/excel_verifier_simplified_gui.jpg) -Now switch to the code view of your newly-added user control. Your class needs to reference the following namespace: +Switch to the code view of your user control. Your class requires this namespace: -* **Sdl.FileTypeSupport.Framework.Core.Settings** +- `Sdl.FileTypeSupport.Framework.Core.Settings` -The Settings Bundle --- +## The Settings Bundle -Each plug-in uses a settings bundle to store and retrieve settings. The mechanism for doing that is provided in a separate class called ```VerifierSettings```, which we will implement later (see [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md)). For now, we create an object based on the ```VerifierSettings``` class, through which we access the plug-in properties: +Each plug-in uses a settings bundle to store and retrieve settings. A separate class called `VerifierSettings` handles this mechanism (see [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md)). Create an object based on the `VerifierSettings` class to access the plug-in properties: # [C#](#tab/tabid-1) ```cs VerifierSettings _settings; ``` -*** -Initialize the Plug-in User Interface --- +## Initialize the Plug-in User Interface -When the user raises the plug-in user interface, the control element should be set according to what is stored in the settings bundle, which is handled through the ```_settings``` object (which we declared previously). +When the user opens the plug-in user interface, set the control element according to what is stored in the settings bundle. Use the `_settings` object (declared previously) to handle this: # [C#](#tab/tabid-2) ```cs @@ -49,9 +47,8 @@ public VerifierSettings Settings } } ``` -*** -During initialization the ```UpdateControl``` method is invoked, which sets the state of the enabled check box (checked or unchecked) to the value of the CheckWordArt member of the ```VerifierSettings``` class as shown below. The other setting that needs to be retrieved from the bundle is the maximum word count, i.e. ```MaxWordCount```. +During initialization, the `UpdateControl` method is invoked. It sets the check box state (checked or unchecked) to the value of the `CheckWordArt` member in the `VerifierSettings` class. It also retrieves the other setting, the maximum word count (`MaxWordCount`): # [C#](#tab/tabid-3) ```cs @@ -61,14 +58,12 @@ public void UpdateControl() txt_MaxWordCount.Text = _settings.MaxWordCount.ToString(); } ``` -*** -Save the Settings to the Settings Bundle --- +## Save the Settings to the Settings Bundle -Conversely, the user interface needs to save the check box setting to the settings bundle, e.g. when the user raises the plug-in UI, changes the check box setting, and then clicks **OK** to apply the changed setting to the settings bundle. +When the user opens the plug-in UI, changes the check box setting, and clicks **OK**, save the setting to the settings bundle. -The first setting to save is the state of the check box (checked or unchecked). According to the check box the ```CheckWordArt``` property will be set to True or False: +The first setting to save is the check box state (checked or unchecked). The `CheckWordArt` property is set to True or False according to the check box: # [C#](#tab/tabid-4) ```cs @@ -77,9 +72,8 @@ private void cb_CheckWordArt_CheckedChanged(object sender, EventArgs e) _settings.CheckWordArt = cb_CheckWordArt.Checked; } ``` -*** -The second setting is the maximum word count, which is entered into the UI as a string value. The following function converts the text value to an integer, and sets the ```MaxWordCount``` property of the ```VerifierSettings``` class, if the value is greater than zero: +The second setting is the maximum word count, entered into the UI as a string. Convert the text value to an integer and set the `MaxWordCount` property of the `VerifierSettings` class if the value is greater than zero: # [C#](#tab/tabid-5) ```cs @@ -93,12 +87,11 @@ private void txt_MaxWordCount_TextChanged(object sender, EventArgs e) } } ``` -*** -Putting it all Together --- +## Putting It All Together + +The complete class should look as follows: -The complete class should look as shown below: # [C#](#tab/tabid-6) ```cs using System; @@ -111,25 +104,22 @@ using System.Text; using System.Windows.Forms; using Sdl.FileTypeSupport.Framework.Core.Settings; - namespace Sdk.FileTypeSupport.Samples.WordArtVerifier { /// - /// Implements theuUser interface through which the settings of the verification plug-in - /// are configured, i.e. the maximum word count and enabling / disabling the verification. + /// Implements the user interface through which the verification plug-in settings are + /// configured: the maximum word count and enabling/disabling verification. /// public partial class SettingsUI : UserControl, IFileTypeSettingsAware { /// /// Create a settings object based on the VerifierSettings class. /// - #region "SettingsObject" VerifierSettings _settings; - #endregion /// - /// Initalize the user interface control by setting it to the - /// setting value stored in the settings bundle. + /// Initialize the user interface control by setting it to the value + /// stored in the settings bundle. /// public SettingsUI() { @@ -137,42 +127,33 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier } /// - /// Reset the user interface control to its default value, which is - /// checked, i.e. the verification functionality should be enabled - /// by default. + /// Reset the user interface control to its default value: checked, + /// which enables verification functionality by default. /// - #region "UpdateControl" public void UpdateControl() { cb_CheckWordArt.Checked = _settings.CheckWordArt; txt_MaxWordCount.Text = _settings.MaxWordCount.ToString(); } - #endregion - /// - /// Save the settings based on the value of the check box. - /// The setting is saved through the VerifierSettings class, which - /// handles the plug-in settings bundle. + /// Save the settings based on the check box value. The setting is saved through + /// the VerifierSettings class, which handles the plug-in settings bundle. /// /// /// - #region "SaveSettingEnabled" private void cb_CheckWordArt_CheckedChanged(object sender, EventArgs e) { _settings.CheckWordArt = cb_CheckWordArt.Checked; } - #endregion /// - /// Save the settings based on the value of the maximum word count text field. - /// Note that the word count is a string value, which needs to be converted to an integer. - /// The setting is saved through the VerifierSettings class, which - /// handles the plug-in settings bundle. + /// Save the settings based on the maximum word count text field value. Note that the + /// word count is a string value that must be converted to an integer. The setting is + /// saved through the VerifierSettings class, which handles the plug-in settings bundle. /// /// /// - #region "SaveSettingMaxCount" private void txt_MaxWordCount_TextChanged(object sender, EventArgs e) { int tempvalue = 0; @@ -182,9 +163,11 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier _settings.MaxWordCount = tempvalue; } } - #endregion - #region "Initialize" + /// + /// Implementation of IFileTypeSettingsAware allowing the Filter Framework + /// to pass through the user settings so that we can initialize the UI. + /// public VerifierSettings Settings { get @@ -197,21 +180,14 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier UpdateControl(); } } - #endregion } } ``` -*** - -See Also --- - - -[Implement the UI Controller Class](implement_the_ui_controller_class_bil.md) +## See Also -[Loading and Saving the Settings](loading_and_saving_the_settings_bil.md) +- [Implement the UI Controller Class](implement_the_ui_controller_class_bil.md) +- [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/implement_the_user_interface_native.md b/apiconcepts/filetypesupport/implement_the_user_interface_native.md index 6144129fef..a7deb91d2b 100644 --- a/apiconcepts/filetypesupport/implement_the_user_interface_native.md +++ b/apiconcepts/filetypesupport/implement_the_user_interface_native.md @@ -1,36 +1,31 @@ -Implement the User Interface -=== +# Implement the User Interface -In this chapter you will learn how to implement the user interface of your verification plug-in. +Implement the user interface of your verification plug-in. -Add a User Control --- +## Add a User Control -Implement the graphical user interface by adding a user control, which you can name, e.g. **SettingsUI.cs**. This is the interface that users will see when configuring the file type plug-in in Var:ProductName through, e.g. **File** > **Options** > **File Types**. Our simple native verifier will only implement one setting, through which users can configure whether to enable the verification function or to disable it. Therefore, you only need to add one check box to the user control, which we call ```cb_Enabled```. +Implement the graphical user interface by adding a user control, for example **SettingsUI.cs**. This is the interface users see when configuring the file type plug-in in `Var:ProductName` through **File** > **Options** > **File Types**. Our simple native verifier implements one setting: whether to enable or disable the verification function. Add one check box to the user control named `cb_Enabled`. -The user interface should look as shown below: +The user interface should look as follows: ![length_checker_settings_page](images/length_checker_settings_page.jpg) -Next, switch to the code view of your newly added user control. This class needs to use the following namespace: +Switch to the code view of your user control. This class requires this namespace: -* **Sdl.FileTypeSupport.Framework.Core.Settings** +- `Sdl.FileTypeSupport.Framework.Core.Settings` -The Settings Bundle --- +## The Settings Bundle -Each plug-in uses a settings bundle to store and retrieve settings. The mechanism for doing that is provided in a separate class called ```VerifierSettings```, which we will implement later (see [Loading and Saving the Settings](loading_and_saving_the_settings_native.md)). Within the controller UI component, we need to create an object based on the ```VerifierSettings``` class: +Each plug-in uses a settings bundle to store and retrieve settings. A separate class called `VerifierSettings` handles this mechanism (see [Loading and Saving the Settings](loading_and_saving_the_settings_native.md)). Create an object based on the `VerifierSettings` class within the controller UI component: # [C#](#tab/tabid-1) ```cs VerifierSettings _settings; ``` -*** -Initialize the Plug-in User Interface --- +## Initialize the Plug-in User Interface -When the user raises the plug-in user interface, the control element should be set according to what is stored in the settings bundle, which is handled through the ```_settings``` object (which we declared previously). +When the user opens the plug-in user interface, set the control element according to what is stored in the settings bundle. Use the `_settings` object (declared previously) to handle this: # [C#](#tab/tabid-2) ```cs @@ -47,10 +42,8 @@ public VerifierSettings Settings } } ``` -*** - -During initialization the UpdateControl method is invoked, which sets the state of the check box (checked or unchecked) to the value of the ```Enabled``` member of the ```VerifierSettings``` class as shown below: +During initialization, the `UpdateControl` method is invoked. It sets the check box state (checked or unchecked) to the value of the `Enabled` member in the `VerifierSettings` class: # [C#](#tab/tabid-3) ```cs @@ -59,12 +52,10 @@ public void UpdateControl() cb_Enable.Checked = _settings.Enable; } ``` -*** -Save the Settings to the Settings Bundle --- +## Save the Settings to the Settings Bundle -Conversely, the user interface needs to save the check box setting to the settings bundle, e.g. when the user raises the plug-in UI, changes the check box setting, and then clicks **OK** to apply the changed setting to the settings bundle: +When the user opens the plug-in UI, changes the check box setting, and clicks **OK**, save the setting to the settings bundle: # [C#](#tab/tabid-4) ```cs @@ -73,12 +64,10 @@ private void cb_Enable_CheckedChanged(object sender, EventArgs e) _settings.Enable = cb_Enable.Checked; } ``` -*** -Putting it all Together --- +## Putting It All Together -If you put it all together, the ```SettingsUI``` class should look as shown below: +Your `SettingsUI` class should look as follows: # [C#](#tab/tabid-5) ```cs @@ -97,20 +86,16 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker /// /// Implements the user interface through which the verification plug-in can be enabled or disabled. /// - #region ClassDeclaration public partial class SettingsUI : UserControl, IFileTypeSettingsAware - #endregion { /// /// Create a settings object based on the VerifierSettings class. /// - #region "SettingsObject" VerifierSettings _settings; - #endregion /// - /// Initalize the user interface control by setting it to the - /// setting value stored in the settings bundle. + /// Initialize the user interface control by setting it to the value + /// stored in the settings bundle. /// public SettingsUI() { @@ -118,32 +103,29 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker } /// - /// Reset the user interface control to its default value, which is - /// checked, i.e. the verification functionality should be enabled - /// by default. + /// Reset the user interface control to its default value: checked, + /// which enables verification functionality by default. /// - #region "UpdateControl" public void UpdateControl() { cb_Enable.Checked = _settings.Enable; } - #endregion /// - /// Save the settings based on the value of the the check box. - /// The setting is saved through the VerifierSettings class, which - /// handles the plug-in settings bundle. + /// Save the settings based on the check box value. The setting is saved through + /// the VerifierSettings class, which handles the plug-in settings bundle. /// /// /// - #region "SaveSetting" private void cb_Enable_CheckedChanged(object sender, EventArgs e) { _settings.Enable = cb_Enable.Checked; } - #endregion - #region "Initialize" + /// + /// Implementation of IFileTypeSettingsAware allowing the Filter Framework + /// to pass through the user settings so that we can initialize the UI. + /// public VerifierSettings Settings { get @@ -156,21 +138,14 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker UpdateControl(); } } - #endregion } } ``` -*** - -See Also --- - - -[Implement the UI Controller Class](implement_the_ui_controller_class_native.md) +## See Also -[Loading and Saving the Settings](loading_and_saving_the_settings_native.md) +- [Implement the UI Controller Class](implement_the_ui_controller_class_native.md) +- [Loading and Saving the Settings](loading_and_saving_the_settings_native.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/implement_the_verification_logic_bil.md b/apiconcepts/filetypesupport/implement_the_verification_logic_bil.md index d3bbd239ce..09cba541e4 100644 --- a/apiconcepts/filetypesupport/implement_the_verification_logic_bil.md +++ b/apiconcepts/filetypesupport/implement_the_verification_logic_bil.md @@ -1,23 +1,22 @@ -Implement the Verification Logic -=== +# Implement the Verification Logic -In this chapter you will learn how to implement the actual verification logic of the bilingual verification plug-in. +Implement the actual verification logic of the bilingual verification plug-in. -Add the Main Verifier Class --- +## Add the Main Verifier Class -Start by adding a class called, e.g. **VerifierMain.cs** to your project. The class needs to reference the following namespaces: +Start by adding a class called, for example, **VerifierMain.cs** to your project. The class requires the following namespaces: -* **Sdl.FileTypeSupport.Framework.NativeApi** -* **Sdl.FileTypeSupport.Framework.BilingualApi**: Provides access to the functionality used for processing bilingual documents. -* **Sdl.FileTypeSupport.Framework.IntegrationApi** -* **Sdl.Core.Settings**: Provides programmatic access to settings bundles +- `Sdl.FileTypeSupport.Framework.NativeApi` +- `Sdl.FileTypeSupport.Framework.BilingualApi` — Provides access to functionality for processing bilingual documents +- `Sdl.FileTypeSupport.Framework.IntegrationApi` +- `Sdl.Core.Settings` — Provides programmatic access to settings bundles -Moreover, your class needs to implement the following interfaces: -* [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml): Provides the methods required for handling bilingual documents. -* [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml): Provides the functionality for initializing the plug-in settings. +Your class must implement these interfaces: -Add the following boolean and string properties. These are the programmatic representation of the plug-in settings, which are set by the class that we implemented previously (see [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md)): +- [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) — Provides methods for handling bilingual documents +- [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) — Provides functionality for initializing plug-in settings + +Add the following boolean and integer properties. These programmatically represent the plug-in settings, which are set by the class implemented previously (see [Loading and Saving the Settings](loading_and_saving_the_settings_bil.md)): # [C#](#tab/tabid-1) ```cs @@ -33,9 +32,10 @@ public int MaxWordCount set; } ``` -*** -Next, implement the ```InitializeSettings``` method of the ```ISettingsAware``` interface. Here, we call on the VerifierSettings class and use the ```PopulateFromSettingsBundle``` method to retrieve the setting from the physically stored settings bundle. To do this, we need to provide the settings bundle object and the file type id (here *Word 2007 v 2.0.0.0 WordArt Verifier*) as parameters. *Word 2007 v 2.0.0.0 WordArt Verifier* is the file type id of the new file type that we will create - see [Create a New File Type Component Builder](create_new_file_type_component_builder.md). The ```CheckWordArt``` and ```MaxWordCount``` properties used in our main verification logic will then be set according to the value retrieved from the settings bundle. +## Initialize Settings + +Implement the `InitializeSettings` method of the `ISettingsAware` interface. Call the `VerifierSettings` class and use the `PopulateFromSettingsBundle` method to retrieve the setting from the stored settings bundle. Provide the settings bundle object and the file type ID (here *Word 2007 v 2.0.0.0 WordArt Verifier*) as parameters. *Word 2007 v 2.0.0.0 WordArt Verifier* is the file type ID of the new file type that you will create (see [Create a New File Type Component Builder](create_new_file_type_component_builder.md)). The `CheckWordArt` and `MaxWordCount` properties are then set according to the values retrieved from the settings bundle: # [C#](#tab/tabid-2) ```cs @@ -47,12 +47,10 @@ public void InitializeSettings(ISettingsBundle settingsBundle, string configurat MaxWordCount = _settings.MaxWordCount; } ``` -*** -Provide Access to the Verification Message Reporting Functionality --- +## Provide Access to the Verification Message Reporting Functionality -If your verifier finds any errors in the file, the user should be notified accordingly. To this end, add the following message reporter member to your class. +When your verifier finds errors, notify the user. Add the following message reporter member to your class: # [C#](#tab/tabid-3) ```cs @@ -62,14 +60,12 @@ public IBilingualContentMessageReporter MessageReporter set; } ``` -*** -The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_) is required for adding error messages (if any) to the **Messages** window of Var:ProductName. +The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IBilingualContentMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_Sdl_FileTypeSupport_Framework_BilingualApi_TextLocation_) method adds error messages to the **Messages** window of `Var:ProductName`. -Provide Access to the Item Factory --- +## Provide Access to the Item Factory -The item factory allows you to create, e.g. structure tags, placeholders, etc. Since our verifier only checks for the number of words in WordArt objects, this functionality is actually not necessary. However, you need to add this member, as it is required by the [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) interface. +The item factory allows you to create structure tags, placeholders, and other elements. Since our verifier only checks the number of words in WordArt objects, this functionality is not necessary. However, you must add this member because the [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) interface requires it: # [C#](#tab/tabid-4) ```cs @@ -79,12 +75,10 @@ public IDocumentItemFactory ItemFactory set; } ``` -*** -Add the Initialize Method --- +## Add the Initialize Method -Add the ```Initialize``` method, through which you can retrieve various information on the verified document such as the source and target language, source count, repetition count, etc. However, our verification logic does not require this information, therefore this member is strictly speaking not necessary for our example, but it must be added according to the [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) interface. +Add the `Initialize` method, which retrieves various information about the verified document such as source and target language, source count, and repetition count. Our verification logic does not require this information, but it must be added according to the [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) interface: # [C#](#tab/tabid-5) ```cs @@ -96,12 +90,10 @@ public void Initialize(IDocumentProperties documentInfo) // This is not required for this implementation. } ``` -*** -Add the File and Process Complete Members --- +## Add the File and Process Complete Members -In a similar manner, the following members need to be added as per the [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) interface, although they are not actually required for the functionality of our plug-in. You may wonder why there is a ```FileComplete``` and a ```Complete``` method, which both seem to serve the same purpose. The reason is that Var:ProductName allows you to merge several documents into one bilingual (SDLXliff) master file (see [Merging files](merging_files.md)). You could use the ```FileComlete``` to carry out an action after the verification of each of the single (merged) files has been completed. You can then call ```Complete``` when the verification process for the entire bilingual document has finished. +Add the following members as required by the [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) interface, although they are not required for your plug-in's functionality. `Var:ProductName` allows you to merge several documents into one bilingual (SDLXliff) master file (see [Merging files](merging_files.md)). Use `FileComplete` to perform an action after verifying each merged file. Use `Complete` when verification of the entire bilingual document finishes: # [C#](#tab/tabid-6) ```cs @@ -123,28 +115,24 @@ public void SetFileProperties(IFileProperties fileInfo) { // A bilingual document can potentially be a master document that contains // a number of single (smaller) bilingual documents. - // The File Info object can be used to access properties of particular bilingual file + // The File Info object can be used to access properties of a particular bilingual file // in a bilingual document, such as the file type definition id, the creation tool. - // This information can be different from biligual file to bilingual file, as - // each single bilingual file might have been created using different - // file types, e.g. one bilingual file was derived from a PPT document, - // another one from a DOC file. + // This information can differ from bilingual file to bilingual file, as each single + // bilingual file might have been created using different file types, e.g. one bilingual + // file was derived from a PPT document, another one from a DOC file. // This is not required for this implementation. - } ``` -*** -Traverse the Paragraph Units --- +## Traverse the Paragraph Units -The ```ProcessParagraphUnit()``` method is used to loop through the paragraph units in the intermediary (SDLXliff) file. This is where we determine whether the actual verification should be applied to a paragraph unit or not. Remember that the verification should only be applied to segments from WordArt objects. +The `ProcessParagraphUnit()` method loops through the paragraph units in the intermediary (SDLXliff) file. Determine whether verification should apply to each paragraph unit. Verification applies only to segments from WordArt objects. -If the ```CheckWordArt``` property (which is set by the user through the UI) is not True, the verification should not be carried out. Otherwise, the method traverses the segment pairs of the current paragraph unit. +If the `CheckWordArt` property (set by the user through the UI) is not True, skip verification. Otherwise, traverse the segment pairs of the current paragraph unit. -Through an ``if`` condition we determine whether the current paragraph unit contains any context information, i.e. whether the context count is greater than zero. If that is the case, we determine the display code of the current context. **TAG** is the display code used (among other things) for WordArt objects. +Use an `if` condition to determine whether the current paragraph unit contains context information (context count > 0). If it does, determine the display code of the current context. **TAG** is the display code used for WordArt objects. -If the display code equals this value and if the context description contains the string wordart, we call the helper function ```CheckWordCount``` (which we will add in the next step). +If the display code equals **TAG** and the context description contains the string "wordart", call the helper function `CheckWordCount` (added in the next step): # [C#](#tab/tabid-7) ```cs @@ -157,8 +145,8 @@ public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) { - // Four conditions have to be met before the word count check is done: - // 1. The current segment needs to have context information (i.e. context count > 0) + // Four conditions must be met before the word count check is done: + // 1. The current segment needs context information (context count > 0) // 2. The display code of the first context information unit is 'TAG' // 3. The context description contains the string 'wordart' // 4. The target segment is not empty @@ -166,31 +154,28 @@ public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) paragraphUnit.Properties.Contexts.Contexts[0].DisplayCode == "TAG" && paragraphUnit.Properties.Contexts.Contexts[0].Description.Contains("wordart") && segmentPair.Target.ToString()!="") - { - { - CheckWordCount(segmentPair.Target); - } - } + { + CheckWordCount(segmentPair.Target); + } } } ``` -*** -Carry out the Actual Word Count Verification --- +## Carry Out the Actual Word Count Verification -Finally, add the following helper function, which checks whether the target segment contains more than the maximum allowed number of words. Our simplified implementation will just work as follows: +Add the following helper function to check whether the target segment contains more than the maximum allowed number of words. This simplified implementation: -* loop through the target segment string and count the number of spaces -* the number of words corresponds to the number of spaces + 1 +- Loops through the target segment string and counts spaces +- Calculates the word count as spaces + 1 -Note that we will not check for non-breaking spaces, hyphens, etc., which is what you might have to do in a 'real', productive implementation. If the number of spaces +1 exceeds the maximum word count, a warning message will be added to the **Messages** window of Var:ProductName. Also, when the translator confirms a WordArt translation that exceeds the maximum word count, a yellow warning icon will be displayed next to the segment in question. -The ReportMessage method takes the following parameters: +Note: This implementation does not check for non-breaking spaces, hyphens, or other word separators, which you might need in a production implementation. If the word count exceeds the maximum, a warning message is added to the **Messages** window of `Var:ProductName`. When the translator confirms a WordArt translation that exceeds the maximum word count, a yellow warning icon displays next to the segment. -* The name of the verifier plug-in that has thrown the message -* The [ErrorLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml), which in this case we set to [Warning](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml#fields). The fact that the word count has been exceeded, is not considered a critical problem, as it does not prevent the translator from generating a valid Microsoft Word target file. The translator is just prompted to re-consider the translation and shorten it. -* A detailed description of the problem, which helps the user ascertain why this segment has been flagged to help him/her take corrective action, i.e. shorten the translation. -* The start and end location of the target string that has caused the problem. By specifying the 'from' and 'up to' location you allow users to jump to the faulty target segment in the document by double-clicking the error message in the **Messages** window of Var:ProductName. +The `ReportMessage` method takes these parameters: + +- The name of the verifier plug-in that reports the message +- The [ErrorLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml), set to [Warning](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml#fields). Exceeding the word count is not critical because it does not prevent generating a valid Microsoft Word target file. It prompts the translator to reconsider the translation and shorten it. +- A detailed description to help users understand why the segment was flagged and take corrective action (shorten the translation) +- The start and end location of the target string that caused the problem. By specifying the 'from' and 'up to' locations, users can jump to the faulty target segment in the document by double-clicking the error message in the **Messages** window of `Var:ProductName` # [C#](#tab/tabid-8) ```cs @@ -215,14 +200,12 @@ private void CheckWordCount(ISegment targetSegment) } } ``` -*** ![Error_Message_Length_Worksheet_Exceeded](images/Error_Message_Length_Worksheet_Exceeded.jpg) -Putting it All Together --- +## Putting It All Together -The complete verification class should now look as shown below: +The complete verification class should look as follows: # [C#](#tab/tabid-9) ```cs @@ -235,7 +218,6 @@ using Sdl.FileTypeSupport.Framework.NativeApi; using Sdl.FileTypeSupport.Framework.BilingualApi; using Sdl.FileTypeSupport.Framework.IntegrationApi; - namespace Sdk.FileTypeSupport.Samples.WordArtVerifier { class VerifierMain : IBilingualVerifier, ISettingsAware @@ -243,8 +225,6 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier /// /// These properties provide access to the two plug-in settings. /// - #region UI settings representation - public bool CheckWordArt { get; @@ -256,14 +236,12 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier get; set; } - #endregion /// /// Initializes the plug-in settings, so that they can be used during the actual verification. /// /// /// - #region "InitializeSettings" public void InitializeSettings(ISettingsBundle settingsBundle, string configurationId) { VerifierSettings _settings = new VerifierSettings(); @@ -271,36 +249,27 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier CheckWordArt = _settings.CheckWordArt; MaxWordCount = _settings.MaxWordCount; } - #endregion - #region "IBilingualFilterComponent Members" /// /// Provides access to the message reporter, which is responsible for - /// outputting any messages in the user interface of Trados Studio - /// /// - #region "messagereporter" + /// outputting any messages in the user interface of Trados Studio. + /// public IBilingualContentMessageReporter MessageReporter { get; set; } - #endregion /// /// Not required in this implementation. Provides access to elements /// such as tags, placeholders, etc. /// - #region "itemfactory" public IDocumentItemFactory ItemFactory { get; set; } - #endregion - #endregion - - #region "IBilingualContentHandler Members" /// /// These members of the IBilingualContentHandler interface are not used in this /// implementation. @@ -319,36 +288,29 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier { // A bilingual document can potentially be a master document that contains // a number of single (smaller) bilingual documents. - // The File Info object can be used to access properties of particular bilingual file + // The File Info object can be used to access properties of a particular bilingual file // in a bilingual document, such as the file type definition id, the creation tool. - // This information can be different from biligual file to bilingual file, as - // each single bilingual file might have been created using different - // file types, e.g. one bilingual file was derived from a PPT document, - // another one from a DOC file. + // This information can differ from bilingual file to bilingual file, as each single + // bilingual file might have been created using different file types, e.g. one bilingual + // file was derived from a PPT document, another one from a DOC file. // This is not required for this implementation. - } - #endregion - #region "InitializeMethod" public void Initialize(IDocumentProperties documentInfo) { // Through the document properties you can access information that is // common to ALL bilingual files in a master bilingual document, e.g. the // source/target language, the repetition/source count, etc. // This is not required for this implementation. - } - #endregion + } /// /// This method implements the actual verification logic. - /// If CheckWordArt is true, the method loops through all segment pairs, and - /// determines whether they have any context information. If true, and if - /// the display code equals 'WA' (WordArt), a separate helper function is called - /// to check the word count. + /// If CheckWordArt is true, the method loops through all segment pairs and + /// determines whether they have context information. If true and if the display code + /// equals 'TAG' (WordArt), a separate helper function checks the word count. /// /// - #region process paragraph unit public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) { if (!CheckWordArt) @@ -358,8 +320,8 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) { - // Four conditions have to be met before the word count check is done: - // 1. The current segment needs to have context information (i.e. context count > 0) + // Four conditions must be met before the word count check is done: + // 1. The current segment needs context information (context count > 0) // 2. The display code of the first context information unit is 'TAG' // 3. The context description contains the string 'wordart' // 4. The target segment is not empty @@ -367,23 +329,18 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier paragraphUnit.Properties.Contexts.Contexts[0].DisplayCode == "TAG" && paragraphUnit.Properties.Contexts.Contexts[0].Description.Contains("wordart") && segmentPair.Target.ToString()!="") - { - { - CheckWordCount(segmentPair.Target); - } - } + { + CheckWordCount(segmentPair.Target); + } } } - #endregion /// /// Helper function that counts the words in the current target segment. - /// If the word count (i.e. number of spaces + 1) exceeds the maximum count - /// that was set through the properties, a message should be added to the - /// Messages window of Trados Studio. + /// If the word count (number of spaces + 1) exceeds the maximum count set through + /// the properties, a message is added to the Messages window of Trados Studio. /// /// - #region output message private void CheckWordCount(ISegment targetSegment) { int pos = 0, count = 0; @@ -404,17 +361,13 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier new TextLocation(new Location(targetSegment,false), targetSegment.ToString().Length-1)); } } - #endregion } } ``` -*** -Using the Main Verifier Class --- +## Using the Main Verifier Class -To use this verifier, a new file type definition based upon the Microsoft Word 2007 file type definition needs to be created (see [Create a New File Type Component Builder](create_new_file_type_component_builder.md)). +To use this verifier, create a new file type definition based on the Microsoft Word 2007 file type definition (see [Create a New File Type Component Builder](create_new_file_type_component_builder.md)). ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/implement_the_verification_logic_native.md b/apiconcepts/filetypesupport/implement_the_verification_logic_native.md index 42ce8cef65..3deab4aca9 100644 --- a/apiconcepts/filetypesupport/implement_the_verification_logic_native.md +++ b/apiconcepts/filetypesupport/implement_the_verification_logic_native.md @@ -1,36 +1,32 @@ -Implement the Verification Logic -=== +# Implement the Verification Logic -In this chapter you will learn how to implement the actual verification logic of our native verifier plug-in. +Implement the actual verification logic of the native verifier plug-in. -Add the Verification Class --- +## Add the Verification Class -In this chapter, we implement the verification functionality. Start by adding a class called e.g. **XMLCheckerMain.cs**. This class needs to use the following namespaces: +Implement the verification functionality by adding a class called, for example, **XMLCheckerMain.cs**. This class requires the following namespaces: -* **Sdl.FileTypeSupport.Framework.NativeApi**: Provides access the functionality to be applied to native file types: -* **Sdl.Core.Settings**: Provides the functionality for initializing and using the plug-in settings. -* **System.Xml**: As the native file type is XML, this namespace is required for accessing the methods used for XML node processing. +- `Sdl.FileTypeSupport.Framework.NativeApi` — Provides access to functionality for native file types +- `Sdl.Core.Settings` — Provides functionality for initializing and using plug-in settings +- `System.Xml` — Required for XML node processing since the native file type is XML -Moreover, the class needs to use the following interfaces: -* [INativeFileVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml): Provides the methods required for implementing a native verification. -* [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml): Provides the functionality for initializing the plug-in settings. +Your class must implement these interfaces: -Provide Access to the Native File to Verify --- +- [INativeFileVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml) — Provides methods for implementing native verification +- [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) — Provides functionality for initializing plug-in settings -Add the following member to the class, which provides access to important information on the native file such as the name of the file, which you will later load into an XML DOM object. +## Provide Access to the Native File to Verify + +Add the following member to the class, which provides access to important information about the native file such as the file name, which you will later load into an XML DOM object: # [C#](#tab/tabid-1) ```cs private INativeOutputFileProperties _outputFileProperties; ``` -*** -Provide Access to the Verification Settings --- +## Provide Access to the Verification Settings -Now add the following boolean property, which provides programmatic access to the setting of the plug-in settings page according to which the verification logic should be applied or not. +Add the following boolean property, which provides programmatic access to the setting from the plug-in settings page that determines whether verification logic should be applied: # [C#](#tab/tabid-2) ```cs @@ -40,10 +36,8 @@ public bool Enabled set; } ``` -*** - -Next, implement the ```InitializeSettings``` method of the **ISettingsAware** interface. Here, we call on the ```VerifierSettings``` class and use the ```PopulateFromSettingsBundle``` method to retrieve the setting from the physically stored settings bundle. To do this, we need to provide the settings bundle object and the file type id (here *Length Check XML v 1.0.0.0*) as parameters. The ```Enabled``` property used in our main verification logic will then be set according to the value retrieved from the settings bundle. +Implement the `InitializeSettings` method of the `ISettingsAware` interface. Call the `VerifierSettings` class and use the `PopulateFromSettingsBundle` method to retrieve the setting from the stored settings bundle. Provide the settings bundle object and the file type ID (here *Length Check XML v 1.0.0.0*) as parameters. The `Enabled` property is then set according to the value retrieved from the settings bundle: # [C#](#tab/tabid-3) ```cs @@ -54,12 +48,10 @@ public void InitializeSettings(ISettingsBundle settingsBundle, string configurat Enabled = _settings.Enable; } ``` -*** -Provide Access to the Verification Message Reporter --- +## Provide Access to the Verification Message Reporter -If your verifier finds any errors in the file, the user should be notified. For this, add the following message reporter member to your class: +When your verifier finds errors, notify the user. Add the following message reporter member to your class: # [C#](#tab/tabid-4) ```cs @@ -69,14 +61,12 @@ public INativeTextLocationMessageReporter MessageReporter set; } ``` -*** -Through the [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileVerifier_MessageReporter) you can output error messages (if any) to the **Messages** window of Var:ProductName. Users can view these messages and resolve the problem. +Through the [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileVerifier_MessageReporter) you output error messages to the **Messages** window of `Var:ProductName`. Users can view these messages and resolve the problem. -Implement the Actual Verification Logic --- +## Implement the Actual Verification Logic -Add the [Verify](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileVerifier_Verify) method, which is triggered when the user starts the plug-in through trough the menu command **Tools** > **Verify** or by pressing **F8**. This function uses the standard XML API (i.e. the API of the native format) to perform the verification. It loops through all ```displaytext``` elements and checks for the presence of a ```maxlength``` attribute. If this attribute is found, the element content is compared against the maximum length value. If the text exceeds the maximum length, the [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method is used to add an error message (i.e. a message with the highest [ErrorLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml)) to the **Messages** window of Var:ProductName. +Add the [Verify](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileVerifier_Verify) method, which is triggered when the user starts verification through the menu command **Tools** > **Verify** or by pressing **F8**. This method uses the standard XML API to perform verification. It loops through all `displaytext` elements and checks for a `maxlength` attribute. If this attribute exists, the element content is compared against the maximum length value. If the text exceeds the maximum length, the [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method adds an error message to the **Messages** window of `Var:ProductName`: # [C#](#tab/tabid-5) ```cs @@ -108,20 +98,19 @@ public void Verify() } } ``` -*** -The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method takes the following parameters: -* The name of the verifier plug-in that has thrown the message -* The [ErrorLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml), which in this case we set to [Error](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml#fields), which is the highest severity level. -* A detailed description of the problem, which helps the user ascertain what the problem is and take corrective action. -* The location, i.e. the target segment that was found to exceed the specified length limit. Double-clicking the message in the **Messages** window of Var:ProductName will display the segment string in a message box. +The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method takes these parameters: + +- The name of the verifier plug-in that reports the message +- The [ErrorLevel](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml), set to [Error](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ErrorLevel.yml#fields), the highest severity level +- A detailed description of the problem to help users understand what went wrong and take corrective action +- The location (the target segment that exceeded the specified length limit). Double-clicking the message in the **Messages** window of `Var:ProductName` displays the segment string in a message box ![Error_Message_Maxlength_XML_Exceeded](images/Error_Message_Maxlength_XML_Exceeded.jpg) -Provide Access to the Native Output File --- +## Provide Access to the Native Output File -Last, add the following members, which provide programmatic access to the native output file, and thus to information such as the file output path and name, the file encoding, creation date, file type info, etc. These members are not actually required for our sample plug-in, as our simple implementation just checks for adherence to the length limit, but does not do any processing on the native output file. However, these members need to be present in our class according the the [INativeFileVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml) interface. +Add the following members, which provide programmatic access to the native output file and information such as file output path, name, encoding, creation date, and file type info. These members are not required for this sample plug-in because the simple implementation only checks for adherence to the length limit without processing the native output file. However, the [INativeFileVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml) interface requires them: # [C#](#tab/tabid-6) ```cs @@ -130,7 +119,6 @@ public void GetProposedOutputFileInfo(IPersistentFileConversionProperties filePr // Not required for this implementation } - /// /// Provides information on output file. /// @@ -140,12 +128,10 @@ public void SetOutputProperties(INativeOutputFileProperties properties) _outputFileProperties = properties; } ``` -*** -Putting it all Together --- +## Putting It All Together -All put together your main verification class should now look as shown below: +Your main verification class should look as follows: # [C#](#tab/tabid-7) ```cs @@ -159,67 +145,51 @@ using Sdl.Core.Settings; using Sdl.FileTypeSupport.Framework.NativeApi; using Sdl.FileTypeSupport.Framework.IntegrationApi; - namespace Sdk.FileTypeSupport.Samples.XMLChecker { /// /// This class implements the verification logic. Depending on whether the - /// verification plug-in is enabled or not, a verification will be performed - /// when the user of Trados Studio presses F8 or invokes the menu command - /// Tools -> Verify. + /// verification plug-in is enabled or not, verification is performed when the user + /// of Trados Studio presses F8 or invokes the menu command Tools > Verify. /// This class is referenced in the file type definition. /// class XMLCheckerMain : INativeFileVerifier, ISettingsAware { - #region "_outputFileProperties" private INativeOutputFileProperties _outputFileProperties; - #endregion - #region "UISettingsRepresentation" public bool Enabled { get; set; } - #endregion /// /// Initializes the plug-in settings, so that they can be used during the actual verification. /// /// /// - #region "InitializeSettings" public void InitializeSettings(ISettingsBundle settingsBundle, string configurationId) { VerifierSettings _settings = new VerifierSettings(); _settings.PopulateFromSettingsBundle(settingsBundle, "Length Check XML v 1.0.0.0"); Enabled = _settings.Enable; } - #endregion - - - #region "message reporter" public INativeTextLocationMessageReporter MessageReporter { get; set; } - #endregion - /// /// This method implements the main verification logic. - /// First, the XML document is loaded into a DOM object. - /// Then, the method loops through all the 'displaytext' elements, and - /// checks for the presence of a 'maxlength' attribute, which indicates - /// the maximum length in characters. If the target segment text exceeds the - /// length limit specified by the attribute, an error message will be reported. - /// Any length limit violations will be reported through the message reporter, - /// which will fill the Messages window of Trados Studio with the error - /// messages that will be displayed to the end user. + /// First, load the XML document into a DOM object. Then, loop through all 'displaytext' + /// elements and check for a 'maxlength' attribute, which indicates the maximum length + /// in characters. If the target segment text exceeds the length limit specified by the + /// attribute, an error message is reported. Any length limit violations are reported + /// through the message reporter, which fills the Messages window of Trados Studio with + /// error messages displayed to the end user. /// - #region "verification logic" public void Verify() { if (!Enabled) @@ -247,17 +217,12 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker } } } - #endregion - - - #region "INativeOutputSettingsAware Members" public void GetProposedOutputFileInfo(IPersistentFileConversionProperties fileProperties, IOutputFileInfo proposedFileInfo) { // Not required for this implementation } - /// /// Provides information on output file. /// @@ -266,17 +231,13 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker { _outputFileProperties = properties; } - #endregion } } ``` -*** -Using the Main Verifier Class --- +## Using the Main Verifier Class -To use this verifier, a new file type definition based upon the XML file type definition needs to be created (see [Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md)). +Create a new file type definition based on the XML file type definition to use this verifier (see [Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md)). ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/implementing_an_external_file_preview.md b/apiconcepts/filetypesupport/implementing_an_external_file_preview.md index 6d4aaf70d6..3aede2a7ca 100644 --- a/apiconcepts/filetypesupport/implementing_an_external_file_preview.md +++ b/apiconcepts/filetypesupport/implementing_an_external_file_preview.md @@ -1,22 +1,20 @@ -Implementing an External File Preview -=== +# Implementing an External File Preview -In this chapter you will learn how to add a simple document preview function based on the standard Windows Notepad application. +This section explains how to add a simple document preview that uses Windows Notepad. -Extend the File Type Component Builder --- +## Extend the File Type Component Builder -Our aim is to enable the file type plug-in to generate an ad-hoc preview in an external application. This allows users to view the file in its native format. +Enable the file type plug-in to generate an ad-hoc preview in an external application. This lets users view the file in its native format. -When processing DOC files, for example, Var:ProductName launches Microsoft Word as external preview application. Since we are dealing with a simple text format, we can use a common text editor such Notepad as external preview application. +For example, when users preview DOC files, Var:ProductName launches Microsoft Word as the external preview application. Because this sample uses a simple text format, Notepad works well as the external preview application. -What makes implementing the external preview easy is the fact that the application logic required for generating an external preview already exists in our sample file type plug-in - to be more precise, in the file writer class, which you implemented in the previous chapter (see [Implementing the File Writer](implementing_the_file_writer.md)). Therefore, all you need to do is register the external preview application in the File Type Component Builder. +The sample file type plug-in already contains the logic required to generate an external preview. The file writer class that you created in the previous chapter provides that logic. See [Implementing the File Writer](implementing_the_file_writer.md). To enable the preview, register the external preview application in the File Type Component Builder. -First, we recommend that you add the name of the preview application to the resources file of your project properties. This is the application name that users will see when accessing the external preview menu command in Var:ProductName. +First, add the name of the preview application to the resource file in your project properties. Users will see this name when they access the external preview command in Var:ProductName. ![ExternalPreview_Name](images/ExternalPreview_Name.jpg) -Now add the method shown below to the File Type Component Builder. Note how the external preview application name is referenced. Also note that this implements the external preview both for the source and the target content. +Now add the following method to the File Type Component Builder. The example references the external preview application name from resources. It also enables the external preview for both source and target content. # [C#](#tab/tabid-1) ```cs @@ -45,7 +43,7 @@ previewFactory.GetPreviewSets(null).Add(externalPreviewSet); ``` *** -Now change the File Type Component Builder to include the external preview. Here the Microsoft Notepad application is used by ```GenericExternalPreviewApplication``` +Now update the File Type Component Builder to include the external preview. In this example, `GenericExteralPreviewApplication` launches Microsoft Notepad. # [C#](#tab/tabid-2) ```cs @@ -62,13 +60,13 @@ public IAbstractPreviewApplication BuildPreviewApplication(string name) ``` *** -You will also need to add an assembly reference to Sdl.FileTypeSupport.Framework.PreviewControls. +Add an assembly reference to `Sdl.FileTypeSupport.Framework.PreviewControls`. >[!NOTE] > ->You can also pass an empty string to the ApplicationPath property. In this case the external preview will call the application that is registered in the OS for this particular file type. +> You can also pass an empty string to the `ApplicationPath` property. In that case, the external preview calls the application that the operating system registers for that file type. -When accessing the **File** > **View** In menu command of Var:ProductName you should now see the following: +When you open **File** > **View In** in Var:ProductName, you should now see the following option: ![PreviewApplication](images/PreviewApplication.jpg) diff --git a/apiconcepts/filetypesupport/implementing_quickinsert_functionality.md b/apiconcepts/filetypesupport/implementing_quickinsert_functionality.md index e5f6e3f707..a6d3f75c17 100644 --- a/apiconcepts/filetypesupport/implementing_quickinsert_functionality.md +++ b/apiconcepts/filetypesupport/implementing_quickinsert_functionality.md @@ -1,22 +1,20 @@ -Implementing QuickInsert Functionality -=== +# Implementing QuickInsert functionality -QuickInsert allows you to further enhance your file type plug-in by adding functionality that allows users to quickly insert inline tags, placeholders, strings (or string pairs), characters that are difficult to type on some keyboards (e.g. ç, ©), etc. +QuickInsert extends your file type plug-in by letting users insert inline tags, placeholders, strings, string pairs, and characters that may be difficult to type on some keyboards, such as ç or ©. -About QuickInsert --- +## About QuickInsert -QuickInsert (formerly QuickTag) allows the insertion of bilingual content into the localizable document using the buttons on the **QuickInsert** toolbar of Var:ProductName. The bilingual content consists of bilingual File Type Support Framework items such as [ITagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ITagPair.yml), [IPlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IPlaceholderTag.yml), [IText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IText.yml), [Location](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.Location.yml), [ICommentMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ICommentMarker.yml), or [ILockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILockedContent.yml). +QuickInsert, formerly QuickTag, inserts bilingual content into the localizable document through the **QuickInsert** toolbar in Var:ProductName. This bilingual content can include File Type Support Framework items such as [ITagPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ITagPair.yml), [IPlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IPlaceholderTag.yml), [IText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IText.yml), [Location](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.Location.yml), [ICommentMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ICommentMarker.yml), and [ILockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILockedContent.yml). -QuickInsert allows users to insert various items into their target segments: +QuickInsert lets users insert the following items into target segments: -* **Inline tags**: for example, tag pairs that apply bold formatting -* **Text pairs**: start and end text to be inserted before and after the current selection, for example, German smart quotes to be inserted before and after the selection -* **Standalone text**: simple pieces of text, e.g. special characters like ®, which replaces the current selection when inserted +- **Inline tags**: for example, tag pairs that apply bold formatting +- **Text pairs**: start and end text inserted before and after the current selection, for example German smart quotes +- **Standalone text**: simple text such as special characters like ®, which replaces the current selection when inserted -QuickInsert items can be specific to particular file types. For example, HTML uses **B** tags to apply bold formatting, while DOC files use **CF** tags. Therefore, each file type plug-in can be associated with its own set of QuickInsert items. +QuickInsert items can be specific to a file type. For example, HTML uses **B** tags to apply bold formatting, while DOC files use **CF** tags. As a result, each file type plug-in can have its own QuickInsert items. -Below you see an example of how the standard Microsoft Word 2007 file type plug-in is associated with a QuickInsert settings page that lists all the QuickInsert items defined for this file type plug-in. +The following example shows the QuickInsert settings page for the standard Microsoft Word 2007 file type plug-in. >[!NOTE] > @@ -24,32 +22,30 @@ Below you see an example of how the standard Microsoft Word 2007 file type plug- ![WordQuickInsert](images/WordQuickInsert.jpg) -When you open a DOC file in Var:ProductName, the QuickInsert toolbar will look as shown below: +When you open a DOC file in Var:ProductName, the QuickInsert toolbar looks like this: ![WordQuickInsertToolbar](images/WordQuickInsertToolbar.jpg) - -Since we have not assigned any QuickInsert items to our sample file type plug-in, the toolbar will look like this after opening a **.text* file: +Because the sample file type plug-in does not have any assigned QuickInsert items yet, the toolbar looks like this after you open a **.text** file: ![QuickInsertToolbarNonAssigned](images/QuickInsertToolbarNonAssigned.jpg) -Apart from some default assignments of characters that can be used in any format, e.g. dash, copyright, etc., all other toolbar buttons are greyed-out (i.e. not assigned). +Apart from a few default character assignments that work in any format, such as dash and copyright, all other toolbar buttons are unavailable because they are not assigned. -Some of the inactive buttons are by default intended for applying particular types of common character formatting, e.g. bold, underline, etc. Since every format uses different tags for applying these types of formatting, the corresponding QuickInsert assignments have to be made on a file type plug-in-specific basis +Some inactive buttons are intended for common character formatting such as bold and underline. Because formats use different tags for this formatting, you must assign the corresponding QuickInsert items for each file type plug-in. ![DefaultFormattingButtons](images/DefaultFormattingButtons.jpg) -Then, there are a number of unassigned buttons that are intended for receiving customized QuickInsert items, e.g. formatting not covered by the default formatting buttons, strings, string pairs, etc. The generic icons of these buttons can be changed programmatically or through the user interface. +There are also unassigned buttons for custom QuickInsert items such as extra formatting, strings, and string pairs. You can change the generic icons for these buttons programmatically or through the UI. ![QuickInsertCustomButtons](images/QuickInsertCustomButtons.jpg) -Modify the File Type Component Builder --- +## Modify the file type component builder -To associate your sample file type plug-in with a settings page that lists the QuickInsert items, the following code was used in the class **SimpleTextFilterComponentBuilder** within the method **BuildFileTypeInformation**. +To associate your sample file type plug-in with a settings page that lists the QuickInsert items, add the following code to the **BuildFileTypeInformation** method in the **SimpleTextFilterComponentBuilder** class. # [C#](#tab/tabid-1) ```cs @@ -59,25 +55,22 @@ info.WinFormSettingsPageIds = new string[] "QuickInserts_Settings", }; ``` -*** -**WinFormSettingsPageIds** specifies the ids of the settings pages to be associated with a file type plug-in. Here we added **QuickInserts_Settings** so that a settings page that lists the QuickInsert items is associated with this file type plug-in. This code was added in an earlier chapter and so should not be added again. +`WinFormSettingsPageIds` specifies the IDs of the settings pages associated with a file type plug-in. In this example, `QuickInserts_Settings` adds a settings page that lists the QuickInsert items. This code was added in an earlier chapter, so do not add it again. -Since a this **QuickInsert** settings page has been associated, a **QuickInsert** link will be shown below your sample file type plug-in in the **Options** dialog box of Var:ProductName. This is the first time that you have implemented a user interface for your file type plug-in, however, the QuickInsert list is, of course, empty. +After you associate the **QuickInsert** settings page, Var:ProductName shows a **QuickInsert** link under your sample file type plug-in in the **Options** dialog box. This is the first UI that you add for the plug-in, but the QuickInsert list is still empty. -By clicking **Add** you could define your own QuickInsert items. However, this standard user interface is limited insofar as it only allows you to define items for standalone text and text pairs. +You can click **Add** to define your own QuickInsert items. However, this standard UI only supports standalone text and text pairs. ![QuickInsertAdd](images/QuickInsertAdd.jpg) +## Define QuickInsert items programmatically -Define QuickInsert Items Programmatically --- - -You could add QuickInsert items through the user interface and thus deploy them in the settings export format (**.sdlfiletype* file). However, as mentioned above, this approach has its limitations. Generating QuickInsert items programmatically gives you full control over the QuickInsert mechanism. +You can add QuickInsert items through the UI and deploy them in the settings export format as a **.sdlfiletype** file. However, that approach has limits. If you generate QuickInsert items programmatically, you get full control over the QuickInsert mechanism. -Let us assume you want to assign a **B** tag pair to the corresponding default button in the QuickInsert toolbar and assign German quotes (i.e. a text pair) to one of the custom QuickInsert buttons. +Assume that you want to assign a **B** tag pair to the corresponding default button in the QuickInsert toolbar and assign German quotes, a text pair, to one of the custom QuickInsert buttons. -Start by adding a class called e.g. **QuickInsertBuilder.cs** to your project. The class needs to be derived from [AbstractQuickTagBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.IntegrationApi.AbstractQuickTagBuilder.yml). Your class needs to reference the namespace **Sdl.FileTypeSupport.Framework.Core.Utilities.IntegrationApi**. Below you see an example of an implementation that assigns the appropriate tag pair to the standard bold formatting button and a text pair (German quotes) to the first custom QuickInsert button. +Start by adding a class such as **QuickInsertBuilder.cs** to your project. Derive the class from [AbstractQuickTagBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.IntegrationApi.AbstractQuickTagBuilder.yml). The class must reference the **Sdl.FileTypeSupport.Framework.Core.Utilities.IntegrationApi** namespace. The following example assigns the appropriate tag pair to the standard bold formatting button and a text pair, German quotes, to the first custom QuickInsert button. # [C#](#tab/tabid-2) ```cs @@ -124,9 +117,8 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText } } ``` -*** -Add the quick insert builder component to the File Type Component Builder by inserting the following code to your implementation of the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) interface. If you do not add the quick insert builder then this component will never be used by the file type plug-in, even if the quick insert builder component has been implemented in the assembly. +Add the QuickInsert builder component to the File Type Component Builder by inserting the following code in your implementation of the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) interface. If you do not add the QuickInsert builder here, the file type plug-in will never use it, even if the assembly contains the component. # [C#](#tab/tabid-3) ```cs @@ -137,24 +129,18 @@ public IQuickTagsFactory BuildQuickTagsFactory(string name) return quickTags; } ``` -*** - -Note that you need to add the following names and values to the **StringResources** file: +Add the following names and values to the **StringResources** file: ![Resources4Quotes](images/Resources4Quotes.jpg) -The QuickInsert toolbar for your file type plug-in should now look as shown below: +The QuickInsert toolbar for your file type plug-in should now look like this: ![QuickInsertToolbarCustomized](images/QuickInsertToolbarCustomized.jpg) -See Also --- - - - -[Using QuickInserts](using_quickinserts.md) +## See also +- [Using QuickInserts](using_quickinserts.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/implementing_the_file_parser.md b/apiconcepts/filetypesupport/implementing_the_file_parser.md index 928f6fd606..dca857d59b 100644 --- a/apiconcepts/filetypesupport/implementing_the_file_parser.md +++ b/apiconcepts/filetypesupport/implementing_the_file_parser.md @@ -1,16 +1,14 @@ -Implementing the File Parser -=== +# Implementing the File Parser -In this chapter you will learn how to process a native file and make its content available for processing in Var:ProductName. +This section explains how to process a native file and make its content available in Var:ProductName. -Add the File Parser Class --- +## Add the file parser class -Once a given file has been found to be valid, the file parser component is meant to process its content, so that it becomes available for interactive translation in the editor of Var:ProductName, or for batch processing, e.g. automatic pre-translation, file analysis, word count, etc. +After the file sniffer identifies a valid file, the file parser processes its content. That content then becomes available for interactive translation in the editor of Var:ProductName and for batch operations such as pre-translation, file analysis, and word counting. -Files usually contain translatable text as well as strings that need to be protected against editing, such as tags in HTML. The application logic of your parser needs to determine what should be exposed as translatable text and which elements need to be protected against editing. Depending on the complexity of the given format a thorough format analysis might be required. +Files usually contain translatable text and strings that must remain protected, such as HTML tags. Your parser must decide which content to expose for translation and which content to protect. Complex formats can require a more detailed format analysis. -Remember what the simple text format that our file type plug-in needs to process looks like (see below): +The following example shows the simple text format that the sample file type plug-in processes: # [Text](#tab/tabid-1) ``` @@ -20,19 +18,23 @@ Automatically re-open previously edited documents. [Element=text2] Prompt me to re-open previously edited documents. Opens a dialog box on start-up. [Element=text3] -Do not automatically re-open previously edited couments. This is the default option. +Do not automatically re-open previously edited documents. This is the default option. [Element=text4] Prd-Code NCC1504 ``` *** -For more information and processing requirements of this format, please refer back to the chapter Introduction. -Start by adding a class called e.g. **SimpleTextParser.cs** to your project. Since the parser needs to read text files for processing, add the ```System.IO``` namespace to the class. It is recommended that you also add the ```System.Drawing``` namespace. This makes it easier to select colour values, which will be useful for highlighting context information later. Also, add the namespace ```Sdl.FileTypeSupport.Framework.NativeApi``` for processing native formats. Your file parser class needs to be derived from [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml) and implement the interfaces [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). Also, if you have parser specific settings which you need to apply, you also need to implement the [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) method of the [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) interface. The class needs to contain the following members of the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface: +For more information about this format and its processing requirements, see the introduction. -1. [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_): Retrieves important information on the input file such as file name, . path, and encoding. -2. [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput): This method is triggered when the parser starts to read the native input file. You could use this method, for example, to set the progress indicator to the beginning, i.e. 0%. As native input files can be complex and comprehensive, Var:ProductName displays a progress bar upon opening a file. The progress of this indicator can be set programmatically. -3. [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput): This method is triggered when the parser has reached the end of the native input file. You could use this method, for example, to set a progress indicator to 100%. -The minimum amount of code to build a project with a native file parser looks as shown below: +Add a class named **SimpleTextParser.cs** to your project. Because the parser reads text files, add the `System.IO` namespace. Add `System.Drawing` if you want to define colors for context information later. Also add `Sdl.FileTypeSupport.Framework.NativeApi` to work with native formats. Derive your parser class from [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml) and implement [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). If your parser uses custom settings, also implement [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) from [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml). + +The class must include the following members from [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml): + +1. [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) retrieves information about the input file, such as the file name, path, and encoding. +2. [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) runs when the parser starts reading the native input file. You can use it to set the progress indicator to the beginning, for example to 0%. +3. [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput) runs when the parser reaches the end of the native input file. You can use it to set a progress indicator to 100%. + +The following example shows the minimum code required to create a native file parser: # [C#](#tab/tabid-2) ```cs @@ -43,7 +45,7 @@ namespace Sdk.Snippets.Native { public class SimpleTextParser1 : AbstractNativeFileParser, INativeContentCycleAware { - IPersistentFileConversionProperties _fileConversionProperties; + private IPersistentFileConversionProperties _fileConversionProperties; public void SetFileProperties(IFileProperties properties) { @@ -62,18 +64,22 @@ namespace Sdk.Snippets.Native ``` *** -Open the Native Input File --- -Add a [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) method to open the native input file. You can retrieve the input file name and path through the [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath) property, which is implemented by the file conversion properties interface. Here you can also use the method [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) and set the parsing progress value to 0%. Upon opening a file in Var:ProductName a progress bar is raised to indicate the progress of the parsing operation. Through the [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) method you can control this progress bar by setting the byte parameter to an appropriate value. For example, after half of the lines in a given text files have been parsed, you can set the parameter to 50. Below you see how we use the [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) method in our implementation: +## Open the native input file + +Add a [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) method to open the native input file. Retrieve the input file path through [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath), which the file conversion properties interface provides. You can also call [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) here to set the parsing progress to 0%. + +When Var:ProductName opens a file, it displays a progress bar for the parsing operation. Call [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) to control that progress bar. For example, after the parser reads half the lines in a text file, you can set the parameter to `50`. + +The following example shows how to use [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing): # [C#](#tab/tabid-3) ```cs protected override void BeforeParsing() { - // set progress reporter to the beginning + // Set the progress reporter to the beginning. OnProgress(0); - // open the native input file for reading + // Open the native input file for reading. _reader = new StreamReader(_fileConversionProperties.OriginalFilePath); } ``` @@ -81,18 +87,17 @@ protected override void BeforeParsing() >[!NOTE] > ->You may wonder what the difference between [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) and [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) is. Var:ProductName allows you to merge several files into one master document. Such a master document can even contain several documents of different native formats (e.g. DOC and PPT). The [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) method can be used to execute the application logic required before the start of the whole parsing process such as writing meta information into the header of the master file. [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) can contain the logic applied to a particular native file that is merged with other native files. However, in our simple implementation, this use case is not covered. Here, we only use the [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) method to set the progress to 0% and to create a text streamreader object. +> [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) and [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) serve different purposes. Var:ProductName can merge several files into one master document, including files from different native formats such as DOC and PPT. Use [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) for logic that runs before the complete parsing process starts, such as writing metadata into the master file header. Use [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) for logic that applies to a specific native file in that merged set. This simple implementation does not cover that scenario. Here, [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing) only sets progress to 0% and creates a `StreamReader` object. -Parse the Input File --- +## Parse the input file -The [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml) class implements the member [DuringParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_DuringParsing), which you need to override in your file parser class. This method reads the input file from the beginning to the end. +Override [DuringParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_DuringParsing) from [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml). This method reads the input file from beginning to end. # [C#](#tab/tabid-4) ```cs protected override bool DuringParsing() { - // iterate through all lines in the input file + // Iterate through all lines in the input file. while (!_reader.EndOfStream) { ProcessLine(_reader.ReadLine()); @@ -102,7 +107,7 @@ protected override bool DuringParsing() ``` *** -For each line of text you call a separate ```ProcessLine()``` helper function to determine whether a given line contains translatable text or not. +For each line of text, call a separate `ProcessLine()` helper method to determine whether the line contains translatable text. # [C#](#tab/tabid-5) ```cs @@ -121,60 +126,60 @@ private void ProcessLine(string sLine) ``` *** -The ```ProcessLine()``` helper function works as follows: If a line starts with an opening bracket and ends with a closing bracket, we call separate helper functions called ```WriteStructureTag()``` and ```WriteContext```, which we still need to implement. -The ```WriteStructureTag()``` helper is used to write any non-translatable information into a structure tag. The non-translatable text (i.e. the strings enclosed in [*brackets*]) will thus be physically present in the bilingual SDLXliff file, but they will not be exposed to the user. You need to include the non-translatable information in the SDLXliff file, so that the corresponding strings can be written back to the native target file later (generation). +The `ProcessLine()` helper works as follows: if a line starts with an opening bracket and ends with a closing bracket, call separate helper methods named `WriteStructureTag()` and `WriteContext()`. -Since users cannot see the structure tag content in the editor of Var:ProductName, it is recommended (though not required) that you add some context information, which is then shown in the document structure column on the right-hand side of the editor. You can have your file type plug-in display a short descriptive code. By moving the mouse over the corresponding code or by double-clicking the user can display more detailed information, which can sometimes be useful for the translation process. This is what is actually done through a separate ```WriteContext()``` helper function, which we will implement later. +Use `WriteStructureTag()` to write non-translatable information into a structure tag. The non-translatable text, such as the strings enclosed in brackets, remains in the bilingual SDLXliff file, but the editor does not expose it to the user. Include this information in the SDLXliff file so that the generator can write it back to the native target file later. +Because users cannot see structure tag content in the editor of Var:ProductName, consider adding context information. The editor shows this information in the document structure column on the right side. Your file type plug-in can display a short descriptive code. Users can point to that code or double-click it to view more detail. The `WriteContext()` helper method handles this task. -**Output Translatable Text** -If a given line does not start and end with a bracket, then the string can be considered translatable text, and can therefore be exposed to the user for translation. This is done through the helper function ```WriteText()```. +## Output translatable text -The ```WriteText()``` helper uses [CreateTextProperties](../..//api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateTextProperties_System_String_) method ofy properties factory to create a text properties object ([ITextProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ITextProperties.yml)) that contains the localizable text. The actual text of this property can then be output by using the ```Output.Text()``` method. +If a line does not start and end with a bracket, treat it as translatable text and expose it for translation. Use the `WriteText()` helper method for this step. + +The `WriteText()` helper uses [CreateTextProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateTextProperties_System_String_) on the properties factory to create an [ITextProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ITextProperties.yml) object that contains the localizable text. It then outputs that text through `Output.Text()`. # [C#](#tab/tabid-6) ```cs -// output translatable text -private void WriteText(string TextContent) +// Output translatable text. +private void WriteText(string textContent) { - ITextProperties textProperties = PropertiesFactory.CreateTextProperties(TextContent); + ITextProperties textProperties = PropertiesFactory.CreateTextProperties(textContent); Output.Text(textProperties); } ``` *** -**Output Structure Tags** +## Output structure tags -In the same way the ```WriteStructureTag()``` helper function uses the [CreateStructureTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateStructureTagProperties_System_String_) method of the properties factory to output the non-translatable lines as structure tags to the intermediate (SDLXliff) file. When creating the tag property the tag content is passed to the ```Create()``` method as a parameter. The tag property can then be output to the API using the method ```Output.StructureTag()```. +In the same way, `WriteStructureTag()` uses [CreateStructureTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateStructureTagProperties_System_String_) on the properties factory to output non-translatable lines as structure tags in the intermediate SDLXliff file. Pass the tag content to `CreateStructureTagProperties()` and then send the result to the API through `Output.StructureTag()`. # [C#](#tab/tabid-7) ```cs -// output non-translatable text as structure tag -private void WriteStructureTag(string TagContent) +// Output non-translatable text as a structure tag. +private void WriteStructureTag(string tagContent) { - IStructureTagProperties structureTagProperties = PropertiesFactory.CreateStructureTagProperties(TagContent); - structureTagProperties.DisplayText = TagContent; + IStructureTagProperties structureTagProperties = PropertiesFactory.CreateStructureTagProperties(tagContent); + structureTagProperties.DisplayText = tagContent; Output.StructureTag(structureTagProperties); } ``` *** -**Output Context Information** +## Output context information -Context information can help translators do job more effectively. Therefore it is useful (but not required) to have your file type plug-in output some context information. To this end, we will add the ```WriteContext()``` helper function to the file parser class, which looks as shown below: +Context information can help translators work more effectively. For that reason, it is useful, though not required, to output context information from your file type plug-in. The following example shows the `WriteContext()` helper method: # [C#](#tab/tabid-8) ```cs -// output context information, not required, but useful -// information for the translator -private void WriteContext(string ContextContent) +// Output context information for the translator. +private void WriteContext(string contextContent) { IContextProperties contextProperties = PropertiesFactory.CreateContextProperties(); - IContextInfo contextInfo = PropertiesFactory.CreateContextInfo(ContextContent); + IContextInfo contextInfo = PropertiesFactory.CreateContextInfo(contextContent); contextInfo.DisplayCode = "EL"; contextInfo.DisplayName = "Element"; - contextInfo.Description = ContextContent; + contextInfo.Description = contextContent; contextInfo.DisplayColor = Color.Beige; contextProperties.Contexts.Add(contextInfo); Output.ChangeContext(contextProperties); @@ -182,80 +187,72 @@ private void WriteContext(string ContextContent) ``` *** -We use the [CreateContextInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateContextInfo_System_String_) method of the properties factory to generate a context information object, and then output the context properties. As you can see, the context information object can be configured through a range of parameters. These parameters define what is displayed in the document structure column of the editor. -In the editor, users first see the short form (i.e. the display code). In this case, the display code **EL** is shown. When the mouse pointer is moved over the display code, the display name, here **Element** is shown in a tooltip. By double-clicking the display code, users can open a separate dialog box, which shows the entire string, i.e. the description, e.g. **[Element=text3]**. Note that you can specify a background colour for each context element. By assigning different colour to contexts you make it easer for the user to differentiate between different contexts (e.g. headings, paragraphs, footnotes, etc.). +Use [CreateContextInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateContextInfo_System_String_) on the properties factory to generate a context information object, and then output the context properties. These parameters control what the editor displays in the document structure column. + +In the editor, users first see the short form, which is the display code. In this example, the display code is **EL**. When users point to the display code, the editor shows the display name, **Element**, in a tooltip. When users double-click the display code, they can open a dialog box that shows the full string, for example **[Element=text3]**. You can also assign a background color to each context element. Different colors make it easier to distinguish between contexts such as headings, paragraphs, and footnotes. -Once you have implemented these functions and built the solution, you can open a sample file in Var:ProductName. In the translation editor the file will then look as shown below: +After you implement these methods and build the solution, you can open a sample file in Var:ProductName. The translation editor then looks like this: ![SimpleSampleTextInEditor](images/SimpleSampleTextInEditor.jpg) -Note that the inline formatting tags are still exposed as normal, translatable text, which should, of course, not be the case. The next chapter (see [Processing Inline Formatting](processing_inline_formatting.md)) covers the topic of how to enhance the file type plug-in to properly mark up these elements as inline tags and apply the correct formatting to the strings that they enclose. +At this stage, the inline formatting tags still appear as normal translatable text. The next chapter, [Processing Inline Formatting](processing_inline_formatting.md), explains how to mark up these elements as inline tags and apply the correct formatting to the enclosed strings. -Also note that the File Type Support Framework has automatically taken care of the segmentation, i.e. the individual sentences appear in separate cells within the editor. This relieves you of implementing a segmentation logic yourself. +The File Type Support Framework also handles segmentation automatically. As a result, individual sentences appear in separate editor cells, and you do not need to implement segmentation logic yourself. -Below is an example of what the user sees after double-clicking the context display codes. +The following example shows what users see after they double-click a context display code. ![ElementCode](images/ElementCode.jpg) -Close and Release the Input File --- +## Close and release the input file -After having parsed the complete file, you should override the [AfterParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_AfterParsing) method of the abstract native file parser. In this function you can close and release the original file from memory. You can also call the [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) method and set the progress value to 100%. +After the parser finishes reading the file, override [AfterParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_AfterParsing). In this method, close the original file and release it from memory. You can also call [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_) to set progress to 100%. # [C#](#tab/tabid-9) ```cs protected override void AfterParsing() { - //close original file + // Close the original file. _reader.Close(); _reader.Dispose(); _reader = null; - //set progres report to 100% + + // Set the progress report to 100%. OnProgress(100); } ``` *** -Add the Component Reference to the File Type Component Builder --- +## Add the component reference to the File Type Component Builder -Do not forget to reference the file parser component to the File Type Component Builder by inserting the following method: +Reference the file parser component in the File Type Component Builder by adding the following method: # [C#](#tab/tabid-10) ```cs /// /// Gets the file extractor for this component. /// -/// not used here -/// a FileExtractor containing an Simple Text Parser +/// Not used here. +/// A FileExtractor that contains a Simple Text Parser. public virtual IFileExtractor BuildFileExtractor(string name) { var parser = new SimpleTextParser(); parser.LockPrdCodes = true; var extractor = this.FileTypeManager.BuildFileExtractor(this.FileTypeManager.BuildNativeExtractor(parser), this); - extractor.AddFileTweaker(new SimpleFilePreTweaker {RequireValidEncoding = false}); + extractor.AddFileTweaker(new SimpleFilePreTweaker { RequireValidEncoding = false }); return extractor; } ``` *** -See Also --- - - -[Processing Inline Formatting](processing_inline_formatting.md) - -[Enhancing the File Parser to Process the Settings](enhancing_the_file_parser_to_process_the_settings.md) - -[Processing Placeholder Tags](processing_placeholder_tags.md) - -[Handling Tags During Segmentation](handling_tags_during_segmentation.md) - -[Locking Specific Strings](locking_specific_strings.md) - -[Using context information](using_context_information.md) +## See also +- [Processing Inline Formatting](processing_inline_formatting.md) +- [Enhancing the File Parser to Process the Settings](enhancing_the_file_parser_to_process_the_settings.md) +- [Processing Placeholder Tags](processing_placeholder_tags.md) +- [Handling Tags During Segmentation](handling_tags_during_segmentation.md) +- [Locking Specific Strings](locking_specific_strings.md) +- [Using context information](using_context_information.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/implementing_the_file_sniffer.md b/apiconcepts/filetypesupport/implementing_the_file_sniffer.md index fca0b965c9..c467933007 100644 --- a/apiconcepts/filetypesupport/implementing_the_file_sniffer.md +++ b/apiconcepts/filetypesupport/implementing_the_file_sniffer.md @@ -1,25 +1,22 @@ -Implementing the File Sniffer -=== +# Implementing the File Sniffer -In this chapter you will learn how to implement the functionality required for determining whether a given file is valid and can therefore be processed by our sample file type plug-in. +This section explains how to validate a file before your sample file type plug-in processes it. -Determine the Validation Criteria --- +## Determine the validation criteria -For determining whether a given file can be processed by our file type plug-in or not, you can, of course, use the file extension, which is specified in the File Type Component Builder. However, this is not a very reliable criterion. Even if the file extension does match, the file might not be valid for some reason, and can therefore not be processed by the file type plug-in. Also, you need to consider that different file types might share the same extension. +You can use the file extension that you defined in the File Type Component Builder to identify candidate files. However, the extension alone does not provide a reliable validation rule. A file can use the expected extension and still contain unsupported content. Different file types can also share the same extension. -It is therefore important to identify one or more reliable criteria that clearly indicate whether a given file is valid or not. For this simple text file type plug-in, let us assume that a *.text file is valid if the first line starts with the string ```[Version=n]```. +Define one or more checks that clearly identify a valid file. For this simple text file type plug-in, assume that a `.text` file is valid when its first line starts with `[Version=n]`. -If this is the case, the file should be considered valid. Otherwise, the file type plug-in should tell the user that the given file is not supported. It is recommended that you implement this validation functionality in a distinct file sniffer component. +If the file matches this rule, treat it as valid. Otherwise, report that the file type plug-in does not support the file. Implement this validation logic in a dedicated file sniffer component. -Implement the File Sniffer --- +## Implement the file sniffer -Add a new class called e.g. **SimpleTextSniffer.cs** to your project. This class needs to implement the [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml) interface. Your file sniffer class needs to contain the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method, which is part of the native file sniffer interface. This method returns a [SniffInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml) object, which you can set to True or to False, depending on whether the file should be considered valid or not according to specific validation criteria. +Add a new class, for example **SimpleTextSniffer.cs**, to your project. Implement the [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml) interface in that class. The class must include the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method. This method returns a [SniffInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml) object. Set that object to indicate whether the file matches your validation criteria. -Remember, that if you have specific settings which need to be applied to the file sniffer, these can be populated using the ```ISettingsGroup``` which is passed in via the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method. Please see [The File Sniffer](the_file_sniffer.md) for more details. +If the file sniffer requires custom settings, use the `ISettingsGroup` parameter that the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method receives. For more information, see [The File Sniffer](the_file_sniffer.md). -The minimum amount of code required to build a file sniffer component looks as shown below: +The following example shows the minimum code required to create a file sniffer component: # [C#](#tab/tabid-1) ```cs @@ -31,11 +28,10 @@ namespace Sdk.Snippets.Native { class SimpleTextSniffer1 : INativeFileSniffer { - - public SniffInfo Sniff(string nativeFilePath, Language language, Codepage suggestedCodepage, + public SniffInfo Sniff(string nativeFilePath, Language language, Codepage suggestedCodepage, INativeTextLocationMessageReporter messageReporter, ISettingsGroup settingsGroup) { - SniffInfo fileInfo = new SniffInfo(); + var fileInfo = new SniffInfo(); return fileInfo; } } @@ -43,7 +39,7 @@ namespace Sdk.Snippets.Native ``` *** -Now you can add the actual logic required to determine whether a file is supported or not. If the file is supported, set the [IsSupported](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_IsSupported) property to True, otherwise to False. The complete file sniffer class looks as shown below: +Now add the validation logic that determines whether the file is supported. If the file is supported, set [IsSupported](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_IsSupported) to `true`. Otherwise, set it to `false`. The following example shows the complete file sniffer class: # [C#](#tab/tabid-2) ```cs @@ -54,20 +50,14 @@ using Sdl.Core.Globalization; namespace Sdk.Snippets.Native { - // the file sniffer component determines whether a given file - // can be processed by the filter or not class SimpleTextSniffer : INativeFileSniffer { public SniffInfo Sniff(string nativeFilePath, Language language, Codepage suggestedCodepage, INativeTextLocationMessageReporter messageReporter, ISettingsGroup settingsGroup) { - SniffInfo fileInfo = new SniffInfo(); - - StreamReader _reader = new StreamReader(nativeFilePath); + var fileInfo = new SniffInfo(); - if (_reader.ReadLine().StartsWith("[Version=")) - fileInfo.IsSupported=true; - else - fileInfo.IsSupported=false; + using var reader = new StreamReader(nativeFilePath); + fileInfo.IsSupported = reader.ReadLine().StartsWith("[Version="); return fileInfo; } @@ -76,17 +66,12 @@ namespace Sdk.Snippets.Native ``` *** -Add the Component Reference to the File Type Definition --- - -Do not forget to reference the file sniffer component to the File Type Component Builder by implementing the BuildFileSniffer method in your implementation of [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). Remember that failure to do so will mean that this component will never be used by the file type plug-in, even if the sniffer component has been added to the assembly. - -See Also --- - +## Add the component reference to the file type definition +Reference the file sniffer component in the File Type Component Builder by implementing the `BuildFileSniffer` method in your implementation of [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). If you skip this step, Var:ProductName will not use the sniffer component, even though the assembly contains it. -[User Communication Through Messaging](user_communication_through_messaging.md) +## See also +- [User Communication Through Messaging](user_communication_through_messaging.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/implementing_the_file_writer.md b/apiconcepts/filetypesupport/implementing_the_file_writer.md index e3a32b302f..3b345feceb 100644 --- a/apiconcepts/filetypesupport/implementing_the_file_writer.md +++ b/apiconcepts/filetypesupport/implementing_the_file_writer.md @@ -1,16 +1,14 @@ -Implementing the File Writer -=== +# Implementing the File Writer -In this chapter you will learn how to implement the component used for generating the target-language file in its native format. +This section explains how to implement the component that generates the target-language file in its native format. -Add a File Writer Class --- +## Add a file writer class -While the file parser component (see [Implementing the File Parser](implementing_the_file_parser.md) is used to convert the native source file into a bilingual intermediary (SDLXliff) format, the file writer does the exact opposite, i.e. it generates the target file in its native format. This is what happens when the user, for example, saves the current file as target or finalizes a project. +The file parser converts the native source file into a bilingual intermediary SDLXliff file. The file writer performs the reverse operation and generates the target file in its native format. This happens, for example, when users save the current file as target or finalize a project. -Start by adding a **SimpleTextWriter.cs** class to your project. The skeleton writer class looks very similar to the file parser class. Here too, you must reference the namespace ```System.IO```, as you need you can generate a target output file. Then add the namespace ```Sdl.FileTypeSupport.Framework.NativeApi```. +Start by adding a **SimpleTextWriter.cs** class to your project. The skeleton writer class closely resembles the file parser class. Add the `System.IO` namespace because the writer creates a target output file. Then add `Sdl.FileTypeSupport.Framework.NativeApi`. -Your writer class needs be derived from [AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml) and must implement the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface. The writer class implements the same members as the parser class. Therefore, the minimum amount of code required to build a file type plug-in with a file writer looks as shown below: +Derive your writer class from [AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml) and implement [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). The writer class implements the same members as the parser class. The following example shows the minimum code required to build a file type plug-in with a file writer: # [C#](#tab/tabid-1) ```cs @@ -22,8 +20,8 @@ namespace Sdk.Snippets.Native { class SimpleTextWriter : AbstractNativeFileWriter, INativeContentCycleAware { - IPersistentFileConversionProperties _conversionProperties; - StreamWriter _targetFile = null; + private IPersistentFileConversionProperties _conversionProperties; + private StreamWriter _targetFile = null; public void SetFileProperties(IFileProperties properties) { @@ -44,16 +42,15 @@ namespace Sdk.Snippets.Native ``` *** -Remember, if you have writer specific settings, you also need to implement the [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) method of the [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) interface. +If your writer uses custom settings, also implement [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) from [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml). -Create the Output Text File --- +## Create the output text file -First, use the [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) member to apply the logic that creates the native output text file: +Use [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput) to create the native output text file: # [C#](#tab/tabid-2) ```cs -// create the output text file +// Create the output text file. public void StartOfInput() { _targetFile = new StreamWriter(OutputProperties.OutputFilePath); @@ -61,18 +58,16 @@ public void StartOfInput() ``` *** -Output Text and Tags -=== +## Output text and tags -The text writer basically traverses the intermediary (SDLXliff) file and outputs the elements it encounters (e.g. text and inline tags) to the target output file. Override the methods provided by the abstract file writer class ([AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml)) to output these elements. The methods shown below output translatable text, structure tags, and inline start/end tags. +The text writer traverses the intermediary SDLXliff file and writes the elements it encounters, such as text and inline tags, to the target output file. Override the methods that [AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml) provides to output these elements. The following methods output translatable text, structure tags, and inline start and end tags. -Through the method [SegmentEnd](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_SegmentEnd) you determine what should be done after you have written a segment to the native output file. Our simple text format just requires a line break after each segment, which we output using ```WriteLine()```. +Use [SegmentEnd](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_SegmentEnd) to define what happens after the writer outputs a segment to the native file. This simple text format only requires a line break after each segment, so call `WriteLine()`. # [C#](#tab/tabid-3) ```cs -// iterate through the bilingual file -// and add translatable text content and the content of -// any structure and inline tags to the target output file +// Iterate through the bilingual file and write translatable text, +// structure tags, and inline tags to the target output file. public override void StructureTag(IStructureTagProperties tagInfo) { _targetFile.WriteLine(tagInfo.TagContent); @@ -82,8 +77,6 @@ public override void Text(ITextProperties textInfo) { _targetFile.Write(textInfo.Text); } - - public override void InlineStartTag(IStartTagProperties tagInfo) { _targetFile.Write(tagInfo.TagContent); @@ -94,7 +87,7 @@ public override void InlineEndTag(IEndTagProperties tagInfo) _targetFile.Write(tagInfo.TagContent); } -// make sure a line break is inserted after each end of a segment +// Insert a line break after each segment. public override void SegmentEnd() { _targetFile.WriteLine(); @@ -102,7 +95,7 @@ public override void SegmentEnd() ``` *** -At the end we close the output file object and dispose of it in the [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput) member of the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface: +At the end of processing, close and dispose the output file object in [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput) from [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml): # [C#](#tab/tabid-4) ```cs @@ -115,10 +108,9 @@ public void EndOfInput() ``` *** -Putting Everything Together --- +## Put everything together -The complete file writer class should now look as shown below: +The complete file writer class should now look like this: # [C#](#tab/tabid-5) ```cs @@ -130,37 +122,29 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText { class SimpleTextWriter : AbstractNativeFileWriter, INativeContentCycleAware { - IPersistentFileConversionProperties _conversionProperties; - StreamWriter _targetFile = null; + private IPersistentFileConversionProperties _conversionProperties; + private StreamWriter _targetFile = null; - #region "members of INativecontentCycleAware member" public void SetFileProperties(IFileProperties properties) { _conversionProperties = properties.FileConversionProperties; } - #region "output file" - // create the output text file + // Create the output text file. public void StartOfInput() { _targetFile = new StreamWriter(OutputProperties.OutputFilePath); } - #endregion - #region "close" public void EndOfInput() { _targetFile.Close(); _targetFile.Dispose(); _targetFile = null; } - #endregion - #endregion - #region "text and tags" - // iterate through the bilingual file - // and add translatable text content and the content of - // any structure and inline tags to the target output file + // Iterate through the bilingual file and write translatable text, + // structure tags, and inline tags to the target output file. public override void StructureTag(IStructureTagProperties tagInfo) { _targetFile.WriteLine(tagInfo.TagContent); @@ -170,8 +154,6 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText { _targetFile.Write(textInfo.Text); } - - public override void InlineStartTag(IStartTagProperties tagInfo) { _targetFile.Write(tagInfo.TagContent); @@ -182,29 +164,27 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText _targetFile.Write(tagInfo.TagContent); } - // make sure a line break is inserted after each end of a segment + // Insert a line break after each segment. public override void SegmentEnd() { _targetFile.WriteLine(); } - #endregion } } ``` *** -Reference the Component in the File Type Component Builder --- +## Reference the component in the File Type Component Builder -Do not forget to reference the file writer class by adding the following code to the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation: +Reference the file writer class by adding the following code to your [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) implementation: # [C#](#tab/tabid-6) ```cs /// /// Gets the file generator for this component. /// -/// not used herer -/// Null if no file generator is defined +/// Not used here. +/// A file generator for the writer. public virtual IFileGenerator BuildFileGenerator(string name) { var writer = new SimpleTextWriter(); @@ -215,10 +195,10 @@ public virtual IFileGenerator BuildFileGenerator(string name) ``` *** -See Also --- - - +## See also -[Implementing the Preview Writer](implementing_the_preview_writer.md) +- [Implementing the Preview Writer](implementing_the_preview_writer.md) +>[!NOTE] +> +> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. \ No newline at end of file diff --git a/apiconcepts/filetypesupport/implementing_the_preview_writer.md b/apiconcepts/filetypesupport/implementing_the_preview_writer.md index bcfa011156..90b1dfaf32 100644 --- a/apiconcepts/filetypesupport/implementing_the_preview_writer.md +++ b/apiconcepts/filetypesupport/implementing_the_preview_writer.md @@ -1,12 +1,12 @@ -Implementing the Preview Writer -=== +# Implementing the preview writer -In this chapter you will learn how to implement the writer component that generates the HTML code that is going to be displayed in the internal Web browser preview control. +This article shows how to implement the writer that generates the HTML displayed in the internal web browser preview control. -Add the Preview Writer Class --- +## Add the preview writer class -Add a class called e.g. **InternalPreviewWriter.cs** to your project. The class needs to implement the same interfaces and members as the file writer class, which we use for generating the target files in their native format (see [Implementing the File Writer](implementing_the_file_writer.md)). The minimum amount of code required to build a file type plug-in with the internal preview writer looks as shown below: +Add a class such as **InternalPreviewWriter.cs** to your project. The class must implement the same interfaces and members as the file writer class that generates native target files. See [Implementing the File Writer](implementing_the_file_writer.md). + +The following example shows the minimum code required for an internal preview writer: # [C#](#tab/tabid-1) ```cs @@ -22,27 +22,22 @@ namespace Sdk.Snippets.Native public void SetFileProperties(IFileProperties properties) { - } public void StartOfInput() { - } public void EndOfInput() { - } } } ``` -**** -Start the Preview Output --- +## Start the preview output -As preview output we can generate a highly simplified HTML document. First, write the start of the HTML file: +Generate a simplified HTML document for the preview output. Start by writing the opening HTML markup: # [C#](#tab/tabid-2) ```cs @@ -53,12 +48,10 @@ public void StartOfInput() _preview.WriteLine(""); } ``` -*** -Output Text and Tags --- +## Output text and tags -Override the ```Text()``` method to output the translatable strings: +Override the `Text()` method to write translatable strings: # [C#](#tab/tabid-3) ```cs @@ -68,9 +61,8 @@ public override void Text(ITextProperties textInfo) _preview.Write(textInfo.Text); } ``` -*** -Let us assume that you want to insert a line break after each paragraph unit. To do this use the two following override methods to enclose each paragraph in a **DIV** tag pair: +If you want to insert a line break after each paragraph unit, override the following methods and wrap each paragraph in a **DIV** tag pair: # [C#](#tab/tabid-4) ```cs @@ -86,9 +78,8 @@ public override void ParagraphUnitEnd() _preview.Write(""); } ``` -*** -For good measure, enclose each segment in a **SPAN** tag pair. This is not actually required for the moment, but structuring the output through **SPAN** container tags will become important later, when we implement the real-time preview (see [Enhancing the Preview File Writer](enhancing_the_preview_file_writer.md)). +Wrap each segment in a **SPAN** tag pair. This step is not required yet, but this structure becomes useful later when you implement the real-time preview. See [Enhancing the Preview File Writer](enhancing_the_preview_file_writer.md). # [C#](#tab/tabid-5) ```cs @@ -103,9 +94,8 @@ public override void SegmentEnd() _preview.Write(""); } ``` -*** -Now use the two following override methods to output the content of the inline tags. Note that by emitting the HTML tags we will also apply the corresponding character formatting in the Web browser preview control. +Next, override the following methods to write inline tag content. When you emit the HTML tags, the web browser preview control also applies the corresponding character formatting. # [C#](#tab/tabid-6) ```cs @@ -121,14 +111,12 @@ public override void InlineEndTag(IEndTagProperties tagInfo) _preview.Write(tagInfo.TagContent); } ``` -*** -Note that we do not output any structure tag content in this preview. +This preview does not write any structure tag content. -Close the Preview Output --- +## Close the preview output -Last, close the preview as shown below: +Finally, close the preview output: # [C#](#tab/tabid-7) ```cs @@ -139,16 +127,14 @@ public void EndOfInput() _preview.Close(); } ``` -*** -The static HTML preview looks as shown in the following example: +The static HTML preview looks like this: ![StaticHTMLPreview](images/StaticHTMLPreview.jpg) -Putting it All Together --- +## Put it all together -If you put everything together, the preview writer class looks as shown below: +The complete preview writer class looks like this: # [C#](#tab/tabid-8) ```cs @@ -167,24 +153,19 @@ namespace Sdk.Snippets.Native // not used in this implementation } - #region "start output" // start the preview output public void StartOfInput() { _preview = new StreamWriter(OutputProperties.OutputFilePath); _preview.WriteLine(""); } - #endregion - #region "text" // output the translatable strings public override void Text(ITextProperties textInfo) { _preview.Write(textInfo.Text); } - #endregion - #region "para" // each paragraph unit should appear in a new line // therefore use a DIV element public override void ParagraphUnitStart(IParagraphUnitProperties properties) @@ -192,15 +173,11 @@ namespace Sdk.Snippets.Native _preview.WriteLine("
"); } - public override void ParagraphUnitEnd() { _preview.Write("
"); } - #endregion - - #region "segment" // enclose each segment in a SPAN tag pair public override void SegmentStart(ISegmentPairProperties properties) { @@ -211,9 +188,7 @@ namespace Sdk.Snippets.Native { _preview.Write(""); } - #endregion - #region "inline tags" // output any inline tags, // which will also apply the corresponding character formatting public override void InlineStartTag(IStartTagProperties tagInfo) @@ -225,29 +200,20 @@ namespace Sdk.Snippets.Native { _preview.Write(tagInfo.TagContent); } - #endregion - - - #region "end output" // end the preview output public void EndOfInput() { _preview.WriteLine(""); _preview.Close(); } - #endregion } } ``` -*** - -See Also --- - +## See also -[Enhancing the Preview File Writer](enhancing_the_preview_file_writer.md) +- [Enhancing the Preview File Writer](enhancing_the_preview_file_writer.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/implementing_the_settings_ui.md b/apiconcepts/filetypesupport/implementing_the_settings_ui.md index ec2f35a0ec..bd21af9c4f 100644 --- a/apiconcepts/filetypesupport/implementing_the_settings_ui.md +++ b/apiconcepts/filetypesupport/implementing_the_settings_ui.md @@ -1,42 +1,38 @@ -Implementing the Settings UI -=== -In this chapter you will learn how to expose file type plug-in configuration settings through a user interface. +# Implementing the Settings UI -Add an Option to Lock Product Codes -=== +Expose file type plug-in configuration settings through a user interface. -Start by adding a user control element to your WinUI project, which you can call, for example, **SettingsUI.cs**. Add a group box and a check box (named ```cb_LockPrdCodes```) to the control, which should look as shown below: +## Add an Option to Lock Product Codes -![LockPrdCodesOption](images/LockPrdCodesOption.jpg) +Start by adding a user control element to your WinUI project, for example **SettingsUI.cs**. Add a group box and a check box named `cb_LockPrdCodes` to the control: +![LockPrdCodesOption](images/LockPrdCodesOption.jpg) -As product codes should be locked by default, set the **Checked** property to True. +Set the **Checked** property to True, since product codes should be locked by default. -Your **SettingsUI** class needs to use the following namespace: +Your **SettingsUI** class needs the following namespace: -* **Sdl.FileTypeSupport.Framework.Core.Settings** +- `Sdl.FileTypeSupport.Framework.Core.Settings` -The Settings Bundle --- +## The Settings Bundle -Each plug-in uses a settings bundle to store and retrieve settings. The mechanism for doing that is provided in a separate class called **UserSettings**, which we will implement later ([Loading and Saving the Settings](loading_and_saving_settings.md)). For now, we create an object based on the **UserSettings** class: +Each plug-in uses a settings bundle to store and retrieve settings. A separate class called `UserSettings` handles this mechanism (see [Loading and Saving the Settings](loading_and_saving_settings.md)). Create an object based on the `UserSettings` class: # [C#](#tab/tabid-1) ```cs private UserSettings _userSettings; ``` -*** -So that we can obtain the correct user settings for this settings page from the Filter Framework, we need to tell the framework which settings we need. We can do this by implementing [IFileTypeSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeSettingsAware-1.yml): +To obtain the correct user settings for this settings page from the Filter Framework, implement [IFileTypeSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeSettingsAware-1.yml): # [C#](#tab/tabid-2) ```cs public partial class SettingsUI : UserControl, IFileTypeSettingsAware ``` -*** -Initialize the Plug-in User Interface Settings -When the user raises the plug-in user interface, the control element should be set according to what is stored in the settings bundle. This is handled by setting the _userSettings object (which we declared previously) and implementing the Settings property from [IFileTypeSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeSettingsAware-1.yml). +## Initialize the Plug-in User Interface Settings + +When the user opens the plug-in user interface, set the control element according to what is stored in the settings bundle. Do this by setting the `_userSettings` object and implementing the Settings property from [IFileTypeSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeSettingsAware-1.yml): # [C#](#tab/tabid-3) ```cs @@ -53,9 +49,8 @@ public UserSettings Settings } } ``` -*** -During initialization the ```UpdateControl``` method is invoked, which sets the state of the check box (checked or unchecked) to the value of the LockPrdCodes member of the ```UserSettings``` class as shown below: +During initialization, the `UpdateControl` method is invoked. It sets the check box state (checked or unchecked) to the value of the `LockPrdCodes` member in the `UserSettings` class: # [C#](#tab/tabid-4) ```cs @@ -64,12 +59,10 @@ public void UpdateControl() cb_LockPrdCodes.Checked = _userSettings.LockPrdCodes; } ``` -*** -Save the Settings to the Settings Bundle --- +## Save the Settings to the Settings Bundle -Conversely, the user interface needs to save the check box setting to the settings bundle, e.g. when the user raises the plug-in UI, changes the check box setting, and then clicks **OK** to apply the changed setting to the settings bundle: +When the user opens the plug-in UI, changes the check box setting, and clicks **OK**, save the setting to the settings bundle: # [C#](#tab/tabid-5) ```cs @@ -78,12 +71,10 @@ private void cb_LockPrdCodes_CheckedChanged(object sender, EventArgs e) _userSettings.LockPrdCodes = cb_LockPrdCodes.Checked; } ``` -*** -Putting it All Together --- +## Putting It All Together -The full code of your user control looks as shown below: +The full code of your user control: # [C#](#tab/tabid-6) ```cs @@ -102,60 +93,47 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.WinUI /// /// Implements the user interface for the file type definition. /// - #region "ClassDeclaration" public partial class SettingsUI : UserControl, IFileTypeSettingsAware - #endregion { /// /// Create a settings object based on the UserSettings class. /// - #region "SettingsObject" private UserSettings _userSettings; - #endregion /// - /// Initalize the user interface control by setting it to the + /// Initialize the user interface control by setting it to the /// setting value stored in the settings bundle. /// - #region "Initialize" public SettingsUI() { InitializeComponent(); } - #endregion - /// - /// Reset the user interface control to its default value, which is - /// checked, i.e. the product lock option should be enabled - /// by default. + /// Reset the user interface control to its default value: checked, + /// which enables the product lock option by default. /// - #region "UpdateControl" public void UpdateControl() { cb_LockPrdCodes.Checked = _userSettings.LockPrdCodes; } - #endregion /// - /// Save the settings based on the value of the the check box. + /// Save the settings based on the check box value. /// The setting is saved through the UserSettings class, which /// handles the plug-in settings bundle. /// /// /// - #region "SaveSetting" private void cb_LockPrdCodes_CheckedChanged(object sender, EventArgs e) { _userSettings.LockPrdCodes = cb_LockPrdCodes.Checked; } - #endregion /// - /// Implementation of IFileTypeSettingsAware allowing the Filter Framework + /// Implementation of IFileTypeSettingsAware allowing the Filter Framework /// to pass through the user settings so that we can initialize the UI. /// - #region "ApplySettings" public UserSettings Settings { get @@ -168,25 +146,16 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText.WinUI UpdateControl(); } } - #endregion } } ``` -*** - -See Also --- - - - -[Creating a New Assembly for the Settings UI](creating_a_new_assembly_for_the_settings_ui.md) - -[Implementing the UI Controller Class](implementing_the_ui_controller_class.md) -[File type settings](file_type_settings.md) +## See Also -[Loading and Saving the Settings](loading_and_saving_settings.md) +- [Creating a New Assembly for the Settings UI](creating_a_new_assembly_for_the_settings_ui.md) +- [Implementing the UI Controller Class](implementing_the_ui_controller_class.md) +- [File type settings](file_type_settings.md) +- [Loading and Saving the Settings](loading_and_saving_settings.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/implementing_the_ui_controller_class.md b/apiconcepts/filetypesupport/implementing_the_ui_controller_class.md index 890ca6b86e..1edd9d2318 100644 --- a/apiconcepts/filetypesupport/implementing_the_ui_controller_class.md +++ b/apiconcepts/filetypesupport/implementing_the_ui_controller_class.md @@ -1,53 +1,57 @@ -Implementing the UI Controller Class -=== +# Implementing the UI Controller Class -In this chapter you will learn how to implement the class that manages the relationship between the host application, the user settings and the user interface. +Implement the class that manages the relationship between the host application, user settings, and the user interface. -When implementing a settings page for the plug-in user interface you need to cover the following scenarios: +## Settings Page Scenarios -* The user clicks the **Reset to Defaults** button, thereby restoring all control elements to their intended default settings. -* The user clicks **OK**, thereby applying (saving) the settings. -* After changing the control element settings, the user goes to another settings page, which should also save any changes to the form control elements. -* The user clicks the **Cancel** button, any changes to the control settings should be discarded. -A settings page does not implement its own **OK**, **Cancel**, **Reset** buttons, but will rely on the control elements that are provided by the dialog box of the framework, which is made possible through this class. -Below you see an example of a settings page as it is implemented for one of the default file types in Var:ProductName: +A settings page for the plug-in user interface must handle these scenarios: + +- The user clicks **Reset to Defaults**, restoring all control elements to their default settings +- The user clicks **OK**, saving the settings +- The user navigates to another settings page, which should save changes to form control elements +- The user clicks **Cancel**, discarding all changes to control settings + +The settings page does not implement its own **OK**, **Cancel**, or **Reset** buttons. Instead, it uses the control elements provided by the framework's dialog box. + +Below is an example of a settings page as implemented for a default file type in `Var:ProductName`: ![SampleSettingsPage](images/SampleSettingsPage.jpg) -Add the Settings Page --- +## Add the Settings Page -Now you need to add another class, e.g. called **SettingsPage.cs** to your project. This class is used to manage the functions of the user control UI, e.g. it triggers the reset function of the UI when a user clicks the **Reset** button. It is this class that will be registered as a plug-in UI page in the File Type Component Builder (i.e. not the actual user control). +Add another class, for example **SettingsPage.cs**, to your project. This class manages the user control UI functions, such as triggering the reset function when a user clicks **Reset**. This class is registered as a plug-in UI page in the File Type Component Builder, not the actual user control. -Reference the following namespace in this class: +Reference this namespace in your class: -* Sdl.FileTypeSupport.Framework.Core.Settings +- `Sdl.FileTypeSupport.Framework.Core.Settings` -Your ```SettingsPage``` class then needs be derived from the [AbstractFileTypeSettingsPage< SettingsControlType, SettingsType>](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.AbstractFileTypeSettingsPage-2.yml) class providing the types of the settings and the UI control: +Your `SettingsPage` class must derive from the [AbstractFileTypeSettingsPage< SettingsControlType, SettingsType>](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.AbstractFileTypeSettingsPage-2.yml) class, providing the types of the settings and the UI control: # [C#](#tab/tabid-1) ```cs class SettingsPage : AbstractFileTypeSettingsPage ``` -*** -Declaring the Page as a Plug-In. --- +## Declare the Page as a Plug-In -The **Plugin Framework** requires all plug-in pages to be marked with a C# attribute. The plugin framework will then generate a plug-in definition for the assembly based on these attributes which can then be used by other applications. +The plugin framework requires all plug-in pages to be marked with a C# attribute. The framework generates a plug-in definition for the assembly based on these attributes, which other applications can use. -As we are creating a Filter Settings Page we will use the ```FileTypeSettingsPage``` attribute. This attribute requires a unique ID, which will be used to identify this plug-in page at runtime, a name, and a description. If the page needs be localised into other languages, the name and description should be key mappings to the related **PluginResources.resx** file in your assembly. +For a Filter Settings Page, use the `FileTypeSettingsPage` attribute. This attribute requires: + +- A unique ID to identify the plug-in page at runtime +- A name +- A description + +If you need to localize the name and description into other languages, use key mappings to the **PluginResources.resx** file in your assembly: # [C#](#tab/tabid-2) ```cs [FileTypeSettingsPage(Id="SimpleText_Settings", Name="Settings_Name", Description="Settings_Description")] ``` -*** -Implementing the Base Class --- +## Implement the Base Class -The ```FileTypeSettingsPage``` base class takes care of a lot of the plumbing required to make sure all the objects are loaded correctly and updated at the correct points. However, because we are not using data binding in our control, the UI must manually be told when settings have been changed. The two methods that make settings changes are ```ResetToDefaults``` and Refresh so we need to override them and make a call to our ```UpdateControl``` method on the UI to inform it that the underlying settings data has changed. +The `FileTypeSettingsPage` base class handles much of the plumbing to ensure objects load correctly and update at the right points. However, since our control does not use data binding, you must manually inform the UI when settings change. Override the `ResetToDefaults` and `Refresh` methods and call `UpdateControl` on the UI to notify it that the underlying settings data has changed: # [C#](#tab/tabid-3) ```cs @@ -57,7 +61,7 @@ public override void ResetToDefaults() Control.UpdateControl(); } ``` -*** + # [C#](#tab/tabid-4) ```cs public override void Refresh() @@ -66,12 +70,10 @@ public override void Refresh() Control.UpdateControl(); } ``` -*** -Add the file type settings page to the file type plug-in --- +## Add the File Type Settings Page to the File Type Plug-In -To associate your sample file type plug-in with this file type settings page the following code was used in the class **SimpleTextFilterComponentBuilder** within the method **BuildFileTypeInformation**. +To associate your sample file type plug-in with this settings page, use the following code in the `SimpleTextFilterComponentBuilder` class within the `BuildFileTypeInformation` method: # [C#](#tab/tabid-5) ```cs @@ -81,18 +83,16 @@ info.WinFormSettingsPageIds = new string[] "QuickInserts_Settings", }; ``` -*** -**WinFormSettingsPageIds** specifies the ids of the settings pages to be associated with a file type plug-in. Here we added **SimpleText_Settings** so that this file type settings page is associated with this file type plug-in. This code was added in an earlier chapter and so should not be added again. +`WinFormSettingsPageIds` specifies the IDs of the settings pages to associate with a file type plug-in. Here, `SimpleText_Settings` associates this settings page with this file type plug-in. (This code was added in an earlier section and should not be repeated.) -After adding this file type settings page, the file type plug-in UI becomes available in the File Type Manager. +After adding this file type settings page, the file type plug-in UI becomes available in the File Type Manager: ![LockProdCodesPage](images/LockProdCodesPage.jpg) -Putting it All Together --- +## Putting It All Together -All put together, your user interface controller class should now look as shown below: +Your user interface controller class should now look as follows: # [C#](#tab/tabid-6) ```cs @@ -101,50 +101,38 @@ using Sdl.FileTypeSupport.Framework.Core.Settings; namespace Sdk.FileTypeSupport.Samples.SimpleText.WinUI { /// - /// This class controls the plug-in user interface. It controls what happens, for example, - /// when the user clicks the button in the user interface for resetting the control elements - /// to their default values. This class is referenced in the file type definition. Without - /// this reference in the SDLFILETPYE file, the plug-in user interface would not be available - /// to the end user. + /// This class controls the plug-in user interface. It controls what happens when the user + /// clicks the button to reset control elements to their default values. This class is referenced + /// in the file type definition. Without this reference in the SDLFILETYPE file, the plug-in + /// user interface would not be available to the end user. /// - #region "SettingsPagePlugin" [FileTypeSettingsPage(Id="SimpleText_Settings", Name="Settings_Name", Description="Settings_Description")] - #endregion - #region "ClassDeclaration" class SettingsPage : AbstractFileTypeSettingsPage - #endregion { /// - /// Triggered, when the user clicks the button Reset to Defaults button in - /// Trados Studio. Restores the default check box state, which should - /// be Checked (i.e. product code strings should be locked). + /// Triggered when the user clicks the Reset to Defaults button in Trados Studio. + /// Restores the default check box state, which should be checked (product code + /// strings should be locked by default). /// - #region "ResetToDefaults" public override void ResetToDefaults() { base.ResetToDefaults(); Control.UpdateControl(); } - #endregion /// - /// Triggered when the user raises the plug-in UI, whose controls (in this case the check box - /// for locking product code strings) will then be set according to the values stored in - /// the settings bundle. + /// Triggered when the user opens the plug-in UI. The controls (in this case, the check box + /// for locking product code strings) are set according to the values stored in the + /// settings bundle. /// - /// - #region "Refresh" public override void Refresh() { base.Refresh(); Control.UpdateControl(); } - #endregion } } ``` -*** ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/initializing_the_file_type_manager.md b/apiconcepts/filetypesupport/initializing_the_file_type_manager.md index a267610fa7..10ae08efd1 100644 --- a/apiconcepts/filetypesupport/initializing_the_file_type_manager.md +++ b/apiconcepts/filetypesupport/initializing_the_file_type_manager.md @@ -1,20 +1,17 @@ +# Initializing the File Type Manager -Initializing the File Type Manager -==== +Learn how applications hosting the file type support framework can initialize the File Type Manager. -This section contains information about how applications hosting the file type support framework can handle initialization of the File Type Manager. +## Overview -The [IFileTypeManager](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeManager.yml) is the main integration point between an application and the file type support framework. The file type manager is typically initialized so that it knows about all file type installed on the system. This section discussed different approaches to that initialization. +The [IFileTypeManager](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeManager.yml) is the main integration point between an application and the file type support framework. The file type manager is typically initialized to recognize all file types installed on the system. This section discusses different approaches to initialization. -Initializing the Filter Manager ---- -The File Type Support Framework is used in an application through the File Type Manager. +## Initializing the Filter Manager -There are different ways for an application to host the File Type Manager. The most straightforward way is to simply create and initialize it expicitly with a list of File Type Component Builders and related settings. +The File Type Support Framework is used in an application through the File Type Manager. There are different ways for an application to host the File Type Manager. The most straightforward way is to create and initialize it explicitly with a list of File Type Component Builders and related settings. > [!Note] -> -> You need a reference to **Sdl.FileTypeSupport.Framework.Core.Utilities** in your project. The example below shows how to do this: +> You need a reference to `Sdl.FileTypeSupport.Framework.Core.Utilities` in your project. The example below shows how to do this: # [C#](#tab/tabid-1) ```cs @@ -24,11 +21,15 @@ filterManager.AddFileTypeDefinition(new SdlXliffFilterComponentBuilder()); // ...additional filter manager initialization goes here... UseFilterManagerForSomething(filterManager); ``` -*** -The example defines in the first line a `PocoFilterManager` (an implementation of [IFileTypeManager](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeManager.yml)) that provides functionality to add new filter definitions. It relies on the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) to build File Type Definitions. In the second line an Open Office Text filter definition is adding using the `OdtFilterDefinitionComponentBuilder` (See [the filter component builder](the_filter_component_builder.md) example) This approach is very straightforward, but it has several implications that are worth noting: +The first line creates a `PocoFilterManager` (an implementation of [IFileTypeManager](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeManager.yml)) that provides functionality to add new filter definitions. It uses the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) to build File Type Definitions. The second line adds an Open Office Text filter definition using the `OdtFilterDefinitionComponentBuilder` (see [the filter component builder](the_filter_component_builder.md) example). -* The application have to explicitly create and manage all the File Type Component Builder classes. -* The application needs to manage their order or priority. This has implications on how the file types are discovered and applied. -* The application is responsible for managing access to the File Type Manager, if it is shared across the application (which is probably preferrable to creating a new one every time, as the initialization could be resource-intensive) -* It is not easy to modify the [FileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeInformation.yml) inside a FilterDefinition. The FilterFramework provides a mechanism to simplify this (see Xml override). +This approach is straightforward, but it has several implications worth noting: + +- Your application must explicitly create and manage all File Type Component Builder classes +- Your application must manage their order or priority, which affects how file types are discovered and applied +- Your application is responsible for managing access to the File Type Manager if it is shared across the application (which is preferable to creating a new instance every time, as initialization is resource-intensive) +- It is not easy to modify the [FileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeInformation.yml) inside a FilterDefinition. The FilterFramework provides a mechanism to simplify this (see XML override). + +> [!NOTE] +> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. \ No newline at end of file diff --git a/apiconcepts/filetypesupport/internal_preview_introduction.md b/apiconcepts/filetypesupport/internal_preview_introduction.md index 94b467d83a..71901a81b3 100644 --- a/apiconcepts/filetypesupport/internal_preview_introduction.md +++ b/apiconcepts/filetypesupport/internal_preview_introduction.md @@ -1,27 +1,24 @@ -Introduction -=== -In this chapter you will learn how to develop a document preview, which goes beyond the features a simple preview document that is shown in an external application. +# Introduction -Enhance your File Type Plug-in by Adding Internal Preview Functionality --- +This section explains how to develop a document preview that offers more functionality than a simple external preview. -Instead of launching an external application such as Microsoft Word or Notepad, you can also generate a preview in a window that is embedded in Var:ProductName. You can implement a static (internal) preview. This means that the source or target text is displayed within Var:ProductName. With this preview type there is no interaction between the side-by-side translation editor and the preview document. +## Add internal preview functionality to your file type plug-in -You may also implement a dynamic real-time preview, which is somewhat more sophisticated, because it interacts with the side-by-side editor of Var:ProductName. This means that when the user selects a segment in the editor, the corresponding segment in the preview will be highlighted and vice versa. +Instead of launching an external application such as Microsoft Word or Notepad, you can generate a preview in a window that Var:ProductName embeds. You can implement a static internal preview, which displays the source or target text inside Var:ProductName. With this preview type, the side-by-side translation editor does not interact with the preview document. -Example of an internal, real-time preview of a DOC file in Var:ProductName: +You can also implement a dynamic real-time preview. This preview type is more advanced because it interacts with the side-by-side editor in Var:ProductName. When users select a segment in the editor, the corresponding segment in the preview is highlighted, and the reverse also applies. + +The following example shows an internal real-time preview of a DOC file in Var:ProductName: ![RealtimePreview](images/RealtimePreview.jpg) -Since our project will require a number of new items, we recommend that you add a new **Preview** folder to your Visual Studio project. Within this folder we will later create an internal preview control and additional classes. +This project requires several new items, so add a **Preview** folder to your Visual Studio project. You will use this folder later for the internal preview control and related classes. ![PreviewFolder](images/PreviewFolder.jpg) -See Also --- - +## See also -[Previewing files](previewing_files.md) +- [Previewing files](previewing_files.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/loading_and_saving_settings.md b/apiconcepts/filetypesupport/loading_and_saving_settings.md index c26aa6dc09..952c81e397 100644 --- a/apiconcepts/filetypesupport/loading_and_saving_settings.md +++ b/apiconcepts/filetypesupport/loading_and_saving_settings.md @@ -1,11 +1,10 @@ -Loading and Saving the Settings -=== +# Loading and Saving the Settings -In this chapter you will learn how to implement the class that is actually responsible for physically the settings and for loading the plug-in settings into the plug-in UI. The physical storing occurs in an **.sdlproj* or in an **.sdltpl* file, which are both XML compliant. +Implement the class responsible for physically storing settings and loading plug-in settings into the plug-in UI. Settings are stored in an **.sdlproj** or **.sdltpl** file, both of which are XML compliant. -**.sdlproj* files are automatically created for each document that is opened for translation/editing in Var:ProductName or for each project that is created in the application. These files contain project-specific information such as the translation memories/termbases used for a project and any project-specific settings, which can also include plug-in settings. An **.sdltpl* file is a project template, which users can create to streamline project creation. +**.sdlproj** files are automatically created for each document opened for translation/editing in `Var:ProductName` or for each project created in the application. These files contain project-specific information such as translation memories, termbases, and project-specific settings, which can include plug-in settings. An **.sdltpl** file is a project template that users can create to streamline project creation. -The settings bundle used by our implementation would look, for example, as shown below: +The settings bundle used by our implementation looks, for example, as follows: # [Xml](#tab/tabid-1) ```xml @@ -13,24 +12,21 @@ The settings bundle used by our implementation would look, for example, as shown True ``` -*** -Each **Setting** element contains an **Id** attribute that denotes the setting (property) name. The **Setting** element encloses the property value, which is changed when the user changes the settings in the UI. +Each **Setting** element contains an **Id** attribute that denotes the setting (property) name. The **Setting** element encloses the property value, which changes when the user modifies the settings in the UI. -Add the UserSettings Class --- +## Add the UserSettings Class -Start by adding a new class to your project called **UserSettings.cs** to the project **Sdl.Sdk.FileTypeSupport.Samples.SimpleText**. Make sure that your class uses the following namespaces: +Add a new class to your project called **UserSettings.cs** in the project **Sdk.FileTypeSupport.Samples.SimpleText**. Your class requires these namespaces: -* **Sdl.Core.Settings** -* **Sdl.FileTypeSupport.Framework.Core.Settings** -Moreover, the class needs to implement the ```FileTypeSettingsBase``` class, which provides the methods required for storing and saving settings to the bundle. +- `Sdl.Core.Settings` +- `Sdl.FileTypeSupport.Framework.Core.Settings` +Your class must implement the `FileTypeSettingsBase` class, which provides the methods required for storing and saving settings to the bundle. -Implement the Setting Property --- +## Implement the Setting Property -In this step, add the property that represents our plug-in setting, in this case the boolean property ```LockPrdCodes```. It determines whether the verification functionality should be active or not. +Add the property that represents the plug-in setting. In this case, add the boolean property `LockPrdCodes`, which determines whether the verification functionality should be active: # [C#](#tab/tabid-2) ```cs @@ -48,12 +44,10 @@ public bool LockPrdCodes } } ``` -*** -Implement the Constructor Method --- +## Implement the Reset to Defaults Method -The ```ResetToDefaults``` method is provided by the base class. In our implementation, it is just overridden to set the ```LockPrdCodes``` property to our default value, True: +Override the `ResetToDefaults` method provided by the base class to set the `LockPrdCodes` property to the default value, True: # [C#](#tab/tabid-3) ```cs @@ -62,12 +56,10 @@ public override sealed void ResetToDefaults() LockPrdCodes = DefaultLockPrdCodes; } ``` -*** -Reset to Defaults --- +## Implement the Constructor Method -Next, implement the constructor method. In this implementation, the constructor just calls on the ```ResetToDefaults``` of the class to set the ```LockPrdCodes``` property to its default value, which is True: +Implement the constructor method. The constructor calls `ResetToDefaults` to set the `LockPrdCodes` property to its default value, which is True: # [C#](#tab/tabid-4) ```cs @@ -76,34 +68,29 @@ public UserSettings() ResetToDefaults(); } ``` -*** -Set the LockPrdCodes Property to the Value from the Settings Bundle --- +## Populate Settings from the Settings Bundle -The base class provides the ```PopulateFromSettingsBundle``` method to retrieve the current setting from the bundle in the **.sdlproj* file and set the ```LockPrdCodes``` property of our implementation accordingly. +The base class provides the `PopulateFromSettingsBundle` method to retrieve the current setting from the bundle in the **.sdlproj** file and set the `LockPrdCodes` property accordingly. -In the **.sdlproj* or **.sdltpl* file, a settings bundle can look as shown below: +In the **.sdlproj** or **.sdltpl** file, a settings bundle looks as follows: # [Xml](#tab/tabid-5) ```xml - - - True - - - - True - - - + + True + + + + True + + ``` -*** -A **SettingsBundle** element can enclose a number of **SettingsGroup** nodes. Each settings bundle has a unique id (guid) that is stored in an attribute. The settings bundles are identified by the id of the plug-in that they refer to. A settings group can enclose, for example, file type settings, verification plug-in settings, etc. In the above example the settings bundle encloses one settings group for another File Type Component Builder and another settings group for simple text plug-in. This id is retrieved from the File Type Component Builder (see [Adding the File Type Component Builder](adding_the_file_type_component_builder.md)). +A **SettingsBundle** element encloses a number of **SettingsGroup** nodes. Each settings bundle has a unique ID (GUID) stored in an attribute. Settings bundles are identified by the ID of the plug-in they refer to. A settings group can enclose file type settings, verification plug-in settings, and so on. In the above example, the settings bundle encloses one settings group for another File Type Component Builder and another settings group for the simple text plug-in. This ID is retrieved from the File Type Component Builder (see [Adding the File Type Component Builder](adding_the_file_type_component_builder.md)). -This XML structure is also reflected in the API. Within the ```SaveToSettingsBundle``` method we create a settings group object based on ```ISettingsGroup``` by applying the ```GetSettingsGroup``` method to the settings bundle. This method takes the settings bundle id (e.g. *Simple Text Filter 1.0.0.0*) as string parameter. We then use the ```GetSettingFromSettingsGroup``` method to set the ```LockPrdCodes``` property. This method requires the settings group object, the name of the setting (e.g. ```LockPrdCodes```), and the default value as parameters (e.g. True). +This XML structure is reflected in the API. Within the `SaveToSettingsBundle` method, create a settings group object based on `ISettingsGroup` by calling the `GetSettingsGroup` method on the settings bundle. This method takes the settings bundle ID (for example, *Simple Text Filter 1.0.0.0*) as a string parameter. Then use the `GetSettingFromSettingsGroup` method to set the `LockPrdCodes` property. This method requires the settings group object, the name of the setting (for example, `LockPrdCodes`), and the default value (for example, True) as parameters: # [C#](#tab/tabid-6) ```cs @@ -113,16 +100,14 @@ public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, LockPrdCodes = GetSettingFromSettingsGroup(settingsGroup, SettingsLockPrdCodes, DefaultLockPrdCodes); } ``` -*** -Set the Property to the Values from the Settings Bundle --- +## Save the Properties to the Settings Bundle -The base class also provides the ```SaveToSettingsBundle``` method, which is required to physically store the value of the properties in the bundle of the **.sdlproj* file. +The base class provides the `SaveToSettingsBundle` method, which physically stores the value of the properties in the bundle of the **.sdlproj** file. -Here too, we create a settings group object based on ```ISettingsGroup``` by applying the ```GetSettingsGroup``` method to the settings bundle. +Create a settings group object based on `ISettingsGroup` by calling the `GetSettingsGroup` method on the settings bundle. -Then we use the ```UpdateSettingInSettingsGroup``` method to save the settings into the physical representation. This method takes the settings group object, the setting name (string), the setting value, and the default value as parameters. +Then use the `UpdateSettingInSettingsGroup` method to save the settings into the physical representation. This method takes the settings group object, the setting name (string), the setting value, and the default value as parameters: # [C#](#tab/tabid-7) ```cs @@ -132,12 +117,10 @@ public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string UpdateSettingInSettingsGroup(settingsGroup, SettingsLockPrdCodes, LockPrdCodes, DefaultLockPrdCodes); } ``` -*** -Putting it All Together --- +## Putting It All Together -The complete class should now look as shown below: +The complete class should look as follows: # [C#](#tab/tabid-8) ```cs @@ -147,12 +130,11 @@ using Sdl.Core.Settings; namespace Sdk.FileTypeSupport.Samples.SimpleText { /// - /// This class is used to actually store the settings to the settings bundle, which - /// is physically saved in an *.sdlproj or in an *.sdltpl file. + /// This class stores the settings to the settings bundle, which is physically saved + /// in an *.sdlproj or *.sdltpl file. /// public class UserSettings: FileTypeSettingsBase { - #region "Properties" private const string SettingsLockPrdCodes = "LockPrdCodes"; private const bool DefaultLockPrdCodes = true; private bool _lockPrdCodes; @@ -166,71 +148,54 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText OnPropertyChanged("LockPrdCodes"); } } - #endregion - #region "Constructor" public UserSettings() { ResetToDefaults(); } - #endregion /// - /// Define the default value, which is Enabled, as the product code strings should - /// not be exposed to translation by default. + /// Define the default value: Enabled, because product code strings should not be + /// exposed to translation by default. /// - #region "ResetToDefaults" public override sealed void ResetToDefaults() { LockPrdCodes = DefaultLockPrdCodes; } - #endregion /// - /// This method is used to load the setting from the settings bundle, - /// which is physically stored in an XML-compliant *.sdlproj or *.sdltpl file. + /// Load the setting from the settings bundle, which is physically stored in an + /// XML-compliant *.sdlproj or *.sdltpl file. /// /// - /// - #region "PopulateFromSettingsBundle" + /// public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, string filterDefinitionId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(filterDefinitionId); LockPrdCodes = GetSettingFromSettingsGroup(settingsGroup, SettingsLockPrdCodes, DefaultLockPrdCodes); } - #endregion /// - /// This method is used to store the settings as configured in the plug-in UI - /// in the settings bundle, which means that the settings are physically written - /// into the XML-compliant *.sdlproj or *.sdltpl file. + /// Store the settings as configured in the plug-in UI in the settings bundle. + /// The settings are physically written into the XML-compliant *.sdlproj or + /// *.sdltpl file. /// /// - /// - #region "SaveToSettingsBundle" + /// public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string filterDefinitionId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(filterDefinitionId); UpdateSettingInSettingsGroup(settingsGroup, SettingsLockPrdCodes, LockPrdCodes, DefaultLockPrdCodes); } - #endregion } } ``` -*** - -See Also --- - - - -[Implement the User Interface](implement_the_user_interface_native.md) - -[Implement the UI Controller Class](implement_the_ui_controller_class_native.md) -[Implement the Verification Logic](implement_the_verification_logic_native.md) +## See Also +- [Implement the User Interface](implement_the_user_interface_native.md) +- [Implement the UI Controller Class](implement_the_ui_controller_class_native.md) +- [Implement the Verification Logic](implement_the_verification_logic_native.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/loading_and_saving_the_settings_bil.md b/apiconcepts/filetypesupport/loading_and_saving_the_settings_bil.md index 475b167e83..5e493fd6f0 100644 --- a/apiconcepts/filetypesupport/loading_and_saving_the_settings_bil.md +++ b/apiconcepts/filetypesupport/loading_and_saving_the_settings_bil.md @@ -1,58 +1,37 @@ -Loading and Saving the Settings -=== +# Loading and Saving the Settings -In this chapter we will learn how to implement the class that is actually responsible for physically storing the settings and for loading the plug-in settings into the plug-in UI. The physical storing occurs in an **.sdlproj* or in an **.sdltpl* file, which are both XML compliant. +Implement the class responsible for physically storing settings and loading plug-in settings into the plug-in UI. Settings are stored in an **.sdlproj** or **.sdltpl** file, both of which are XML compliant. -**.sdlproj* files are automatically created for each document that is opened for translation/editing in Var:ProductName or for each project that is created in the application. These files contain project-specific information such as the translation memories/termbases used for a project as well as any project-specific settings, which can also include plug-in settings. An **.sdltpl* file is a project template, which users can create to streamline project creation. +**.sdlproj** files are automatically created for each document opened for translation/editing in `Var:ProductName` or for each project created in the application. These files contain project-specific information such as translation memories, termbases, and project-specific settings, which can include plug-in settings. An **.sdltpl** file is a project template that users can create to streamline project creation. -The settings bundle stored in an **.sdlproj* file as used by our implementation would look, for example, as shown below: +The settings bundle stored in an **.sdlproj** file looks, for example, as follows: # [Xml](#tab/tabid-1) ```xml - True - + True + ``` -*** -Click or drag to resize -Loading and Saving the Settings -In this chapter we will learn how to implement the class that is actually responsible for physically storing the settings and for loading the plug-in settings into the plug-in UI. The physical storing occurs in an *.sdlproj or in an *.sdltpl file, which are both XML compliant. +Each **Setting** element contains an **Id** attribute that denotes the setting (property) name. The **Setting** element encloses the property value, which changes when the user modifies the settings in the UI. -*.sdlproj files are automatically created for each document that is opened for translation/editing in Var:ProductName or for each project that is created in the application. These files contain project-specific information such as the translation memories/termbases used for a project as well as any project-specific settings, which can also include plug-in settings. An *.sdltpl file is a project template, which users can create to streamline project creation. +## Add the VerifierSettings Class -The settings bundle stored in an *.sdlproj file as used by our implementation would look, for example, as shown below: - -# [Xml](#tab/tabid-2) -```xml - - True - -``` -*** - -Each **Setting** element contains an **Id** attribute that denotes the setting (property) name. The **Setting** element encloses the property value, which is changed when the user changes the settings in the UI. - -Add the VerifierSettings Class --- - -Start by adding a new class to your project called ```VerifierSettings```. Make sure that your class uses the following namespaces: - -* **Sdl.Core.Settings** -* **Sdl.FileTypeSupport.Framework.Core.Settings** +Add a new class to your project called **VerifierSettings.cs**. Your class requires these namespaces: +- `Sdl.Core.Settings` +- `Sdl.FileTypeSupport.Framework.Core.Settings` -Moreover, the component needs to be derived from the ```FileTypeSettingsBase``` class, which provides the methods required for storing and saving settings to the bundle. +Your class must be derived from the `FileTypeSettingsBase` class, which provides the methods required for storing and saving settings to the bundle. -Implement the Setting Properties --- +## Implement the Setting Properties -In this step, add the property that represents our plug-in setting, in this case the boolean property ```CheckWordArt```, which determines whether the verification functionality should be active or not. The ```MaxWordCount``` property is used to set or retrieve the maximum number of words a particular segment is allowed to have. +Add the properties that represent the plug-in settings. In this case, add the boolean property `CheckWordArt`, which determines whether the verification functionality should be active. The `MaxWordCount` property stores the maximum number of words a segment is allowed to have. -# [C#](#tab/tabid-3) +# [C#](#tab/tabid-2) ```cs -bool _checkWordArt; -int _maxWordCount; +private bool _checkWordArt; +private int _maxWordCount; public bool CheckWordArt { @@ -74,14 +53,12 @@ public int MaxWordCount } } ``` -*** -Implement the Constructor Method --- +## Implement the Reset to Defaults Method -The ```ResetToDefaults``` method is provided by the base class. In our implementation, it is just overridden to set the ```MaxWordCount``` and ```CheckWordArtproperties``` to their default values, i.e. 3 and True: +Override the `ResetToDefaults` method provided by the base class to set the `CheckWordArt` and `MaxWordCount` properties to their default values: -# [C#](#tab/tabid-4) +# [C#](#tab/tabid-3) ```cs public override void ResetToDefaults() { @@ -89,50 +66,44 @@ public override void ResetToDefaults() MaxWordCount = 3; } ``` -*** -Reset to Defaults --- +## Implement the Constructor Method -Next, implement the constructor method. In this implementation, the constructor just calls on the ```ResetToDefaults``` of the class to set the ```CheckWordArt``` property to its default value, which is True, and 3 as the maximum word count: -# [C#](#tab/tabid-5) +Implement the constructor method. The constructor calls `ResetToDefaults` to set the `CheckWordArt` property to its default value (True) and set the maximum word count to 3: + +# [C#](#tab/tabid-4) ```cs public VerifierSettings() { ResetToDefaults(); } ``` -*** -Set the Properties to the Values from the Settings Bundle --- +## Populate Settings from the Settings Bundle -The base class provides the ```PopulateFromSettingsBundle``` method to retrieve the current setting from the bundle in the **.sdlproj* file and set the ```CheckWordArt``` and the ```MaxWordCount``` properties of our implementation accordingly. +The base class provides the `PopulateFromSettingsBundle` method to retrieve the current settings from the bundle in the **.sdlproj** file and set the `CheckWordArt` and `MaxWordCount` properties accordingly. -In the **.sdlproj* or **.sdltpl* file a settings bundle can look, for example, as shown below: +In the **.sdlproj** or **.sdltpl** file, a settings bundle looks as follows: -# [Xml](#tab/tabid-6) +# [C#](#tab/tabid-5) ```xml - - - 3 - True - - - - True - - - + + 3 + True + + + + True + + ``` -*** -A **SettingsBundle** element can enclose a number of **SettingsGroup** nodes. Each settings bundle has a unique id (guid) that is stored in an attribute. The settings bundles are identified by the id of the plug-in that they refer to. A settings group can enclose, for example, file type settings, verification plug-in settings, etc. In the above example the settings bundle encloses one settings group for the term verifier plug-in and another settings group for our sample WordArt verifier plug-in. This id is retrieved from the File Type Component Builder (see [Create a New File Type Component Builder](create_new_file_type_component_builder.md)). +A **SettingsBundle** element encloses a number of **SettingsGroup** nodes. Each settings bundle has a unique ID (GUID) stored in an attribute. Settings bundles are identified by the ID of the plug-in they refer to. A settings group can enclose file type settings, verification plug-in settings, and so on. In the above example, the settings bundle encloses one settings group for the term verifier plug-in and another settings group for the WordArt verifier plug-in. This ID is retrieved from the File Type Component Builder (see [Create a New File Type Component Builder](create_new_file_type_component_builder.md)). -This XML structure is also reflected in the API. Within the ```SaveToSettingsBundle``` method we create a settings group object based on ```ISettingsGroup``` by applying the ```GetSettingsGroup``` method to the settings bundle. This method takes the settings bundle id (e.g. *Word 2007 v 2.0.0.0*) as string parameter. We then use the ``GetSettingFromSettingsGroup`` method to set the ```CheckWordArt``` and the ```MaxWordCount``` properties. This method requires the settings group object, the name of the setting (e.g. *CheckWordArt*), and the default value as parameters. +This XML structure is reflected in the API. Within the `PopulateFromSettingsBundle` method, create a settings group object based on `ISettingsGroup` by calling the `GetSettingsGroup` method on the settings bundle. This method takes the settings bundle ID (for example, *Word 2007 v 2.0.0.0*) as a string parameter. Then use the `GetSettingFromSettingsGroup` method to retrieve the `CheckWordArt` and `MaxWordCount` properties. This method requires the settings group object, the name of the setting (for example, *CheckWordArt*), and the default value as parameters: -# [C#](#tab/tabid-7) +# [C#](#tab/tabid-6) ```cs public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, string configurationId) { @@ -142,18 +113,16 @@ public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, MaxWordCount = GetSettingFromSettingsGroup(settingsGroup, "MaxWordCount", MaxWordCount); } ``` -*** -Set the Properties to the Values from the Settings Bundle --- +## Save the Properties to the Settings Bundle -The base class also provides the ```SaveToSettingsBundle``` method, which is required to physically store the value of the two properties in the bundle of the *.sdlproj file. +The base class provides the `SaveToSettingsBundle` method, which physically stores the value of the properties in the bundle of the **.sdlproj** file. -Here too, we create a settings group object based on ```ISettingsGroup``` by applying the ```GetSettingsGroup``` method to the settings bundle. +Create a settings group object based on `ISettingsGroup` by calling the `GetSettingsGroup` method on the settings bundle. -Then we use the ```UpdateSettingInSettingsGroup``` method to save the settings into the physical representation. This method takes the settings group object, the setting name (string), the setting value, and the default value as parameters. +Then use the `UpdateSettingInSettingsGroup` method to save the settings into the physical representation. This method takes the settings group object, the setting name (string), the setting value, and the default value as parameters: -# [C#](#tab/tabid-8) +# [C#](#tab/tabid-7) ```cs public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string configurationId) { @@ -163,14 +132,12 @@ public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string UpdateSettingInSettingsGroup(settingsGroup, "MaxWordCount", MaxWordCount, defaults.MaxWordCount); } ``` -*** -Putting it All Together --- +## Putting It All Together -The complete class should now look as shown below: +The complete class should look as follows: -# [C#](#tab/tabid-9) +# [C#](#tab/tabid-8) ```cs using System; using System.Collections.Generic; @@ -183,14 +150,13 @@ using System.Windows.Forms; namespace Sdk.FileTypeSupport.Samples.WordArtVerifier { /// - /// This class is used to actually store the settings to the settings bundle, which - /// is physically saved in an *.sdlproj or in an *.sdltpl file. + /// This class stores the settings to the settings bundle, which + /// is physically saved in an *.sdlproj or *.sdltpl file. /// - public class VerifierSettings: FileTypeSettingsBase + public class VerifierSettings : FileTypeSettingsBase { - #region "Properties" - bool _checkWordArt; - int _maxWordCount; + private bool _checkWordArt; + private int _maxWordCount; public bool CheckWordArt { @@ -211,38 +177,28 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier OnPropertyChanged("MaxWordCount"); } } - #endregion - - #region "Constructor" public VerifierSettings() { ResetToDefaults(); } - #endregion - - #region "OverrideMethods" /// - /// Define the default value, which is Enabled (i.e. true), as the verification function should + /// Define the default value: Enabled (True), as the verification function should /// be active by default, and 3 for the default maximum word count. /// - #region "ResetToDefaults" public override void ResetToDefaults() { CheckWordArt = true; MaxWordCount = 3; } - #endregion - /// - /// This method is used to load the setting from the settings bundle, + /// Load the setting from the settings bundle, /// which is physically stored in an XML-compliant *.sdlproj or *.sdltpl file. /// /// /// - #region "PopulateFromSettingsBundle" public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, string configurationId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(configurationId); @@ -250,17 +206,14 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier CheckWordArt = GetSettingFromSettingsGroup(settingsGroup, "CheckWordArt", CheckWordArt); MaxWordCount = GetSettingFromSettingsGroup(settingsGroup, "MaxWordCount", MaxWordCount); } - #endregion - /// - /// This method is used to store the settings as configured in the plug-in UI - /// in the settings bundle, which means that the settings are physically written + /// Store the settings as configured in the plug-in UI + /// in the settings bundle. The settings are physically written /// into the XML-compliant *.sdlproj or *.sdltpl file. /// /// /// - #region "SaveToSettingsBundle" public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string configurationId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(configurationId); @@ -268,25 +221,15 @@ namespace Sdk.FileTypeSupport.Samples.WordArtVerifier UpdateSettingInSettingsGroup(settingsGroup, "CheckWordArt", CheckWordArt, defaults.CheckWordArt); UpdateSettingInSettingsGroup(settingsGroup, "MaxWordCount", MaxWordCount, defaults.MaxWordCount); } - #endregion - - #endregion } } ``` -*** - -See Also --- - - - -[Implement the User Interface](implement_the_user_interface_bil.md) -[Implement the UI Controller Class](implement_the_ui_controller_class_bil.md) +## See Also -[Implement the Verification Logic](implement_the_verification_logic_bil.md) +- [Implement the User Interface](implement_the_user_interface_bil.md) +- [Implement the UI Controller Class](implement_the_ui_controller_class_bil.md) +- [Implement the Verification Logic](implement_the_verification_logic_bil.md) ->[!NOTE] -> +> [!NOTE] > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. diff --git a/apiconcepts/filetypesupport/loading_and_saving_the_settings_native.md b/apiconcepts/filetypesupport/loading_and_saving_the_settings_native.md index e251628360..b6b2fff883 100644 --- a/apiconcepts/filetypesupport/loading_and_saving_the_settings_native.md +++ b/apiconcepts/filetypesupport/loading_and_saving_the_settings_native.md @@ -1,12 +1,13 @@ -Loading and Saving the Settings -=== +# Loading and Saving the Settings -In this chapter, you will learn how to implement the class that is actually responsible for physically storing the plug-in settings and for loading them. The settings are physically stored in an **.sdlproj* or in an **.sdltpl* file, which are both XML compliant. +Implement a class to store and load plug-in settings. Settings store in **.sdlproj* or **.sdltpl* files, both XML-compliant. -**.sdlproj* files are automatically created for each document that is opened for translation/editing in Var:ProductName or for each project that is created in the application. These files contain project-specific information such as the translation memories/termbases used for a project as well as any other project-specific settings, which can also include plug-in settings. An **.sdltpl* file is a project template, which users can create to streamline project creation. +**.sdlproj* files automatically generate when a document opens for translation/editing in Var:ProductName or when a user creates a project. These files contain project-specific information, including translation memories, termbases, and plug-in settings. An **.sdltpl* file serves as a project template that streamlines project creation. + +Within an **.sdlproj* or **.sdltpl* file, the settings bundle node appears as follows: -Within an **.sdlproj* or **.sdltpl* file the settings bundle node used by our implementation would look, for example, as shown below: # [Xml](#tab/tabid-1) + ```xml True @@ -14,22 +15,20 @@ Within an **.sdlproj* or **.sdltpl* file the settings bundle node used by our im ``` *** -Each **Setting** element contains an **Id** attribute that denotes the setting (property) name. The **Setting** element encloses the property value, which is updated whenever the user changes the settings in the UI. +Each **Setting** element contains an **Id** attribute that denotes the setting (property) name. The **Setting** element encloses the property value, which updates whenever the user changes settings in the UI. -Add the VerifierSettings Class --- +## Add the VerifierSettings Class -Start by adding a new class to your project called ```VerifierSettings```. Make sure that your class uses the following namespaces: +Add a new class called ```VerifierSettings``` to your project. Ensure your class uses the following namespaces: * Sdl.Core.Settings * Sdl.FileTypeSupport.Framework.Core.Settings -Moreover, the class needs to implement the ```FileTypeSettingsBase``` class, which provides the methods required for storing and saving values to the settings bundle. +The class must implement the ```FileTypeSettingsBase``` class, which provides methods for storing and saving values to the settings bundle. -Implement the Setting Property --- +## Implement the Setting Property -In this step, add the property that represents our plug-in setting, in this case the boolean property ```Enabled```. It determines whether the verification functionality should be active or not. +Add the property representing the plug-in setting: the boolean property ```Enabled```, which determines whether verification functionality is active: # [C#](#tab/tabid-2) ```cs @@ -48,10 +47,9 @@ public bool Enable ``` *** -Implement the Constructor Method --- +## Implement the Constructor Method -The ```ResetToDefaults``` method is provided by the base class. In our implementation, it is just overridden to set the ```Enabled``` property to our default value, True: +The base class provides the `ResetToDefaults()` method. Override it to set the `Enabled` property to True: # [C#](#tab/tabid-3) ```cs @@ -62,10 +60,7 @@ public override void ResetToDefaults() ``` *** -Reset to Defaults --- - -Next, implement the constructor method. In this implementation, the constructor just calls on the ```ResetToDefaults``` of the class to set the ``Enabled`` property to its default value, which is True: +Next, implement the constructor method. The constructor calls `ResetToDefaults()` to set the `Enabled` property to True: # [C#](#tab/tabid-4) ```cs @@ -76,12 +71,11 @@ public VerifierSettings() ``` *** -Set the Enabled Property to the Value from the Settings Bundle --- +## Set the Enabled Property from the Settings Bundle -The base class provides the ```PopulateFromSettingsBundle``` method to retrieve the current setting from the bundle in the **.sdlproj* file and to set the Enabled property of our implementation accordingly. +The base class provides the `PopulateFromSettingsBundle()` method to retrieve the current setting from the bundle in the **.sdlproj* file and set the Enabled property accordingly. -In the **.sdlproj* or **.sdltpl* file, a settings bundle can look as shown below: +In the **.sdlproj* or **.sdltpl* file, a settings bundle appears as follows: # [Xml](#tab/tabid-5) ```xml @@ -97,9 +91,9 @@ In the **.sdlproj* or **.sdltpl* file, a settings bundle can look as shown below ``` *** -A **SettingsBundle** element can enclose a number of **SettingsGroup** nodes. Each settings bundle has a unique id (guid) that is stored in an attribute. The settings bundles are identified by the id of the plug-in that they refer to. A settings group can enclose, for example, file type settings, verification plug-in settings, etc. In the above example the settings bundle encloses one settings group for the term verifier plug-in and another settings group that is used by our sample length verifier plug-in. This id is retrieved from the File Type Component Builder (see [Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md)). +A **SettingsBundle** element contains multiple **SettingsGroup** nodes. Each settings bundle has a unique identifier (GUID) in an attribute that identifies it by the plug-in id it refers to. A settings group contains file type settings, verification plug-in settings, and so on. In the example above, the settings bundle contains one settings group for the term verifier plug-in and another for the sample length verifier plug-in. The File Type Component Builder provides this identifier (see [Extending existing File Type Component Builder](extending_existing_file_type_component_builder.md)). -This XML structure is also reflected in the API. Within the ```SaveToSettingsBundle``` method we create a settings group object based on ```ISettingsGroup``` by applying the ```GetSettingsGroup``` method to the settings bundle. This method takes the settings bundle id (e.g. *Length Check XML v 1.0.0.0*) as string parameter. We then use the GetSettingFromSettingsGroup method to set the ```Enabled``` property. This method requires the settings group object, the name of the setting (e.g. *Enabled*), and the default value as parameters (e.g. True). +This XML structure reflects in the API. Within the `PopulateFromSettingsBundle()` method, create a settings group object based on `ISettingsGroup` by calling `GetSettingsGroup()` on the settings bundle. This method accepts the settings bundle id (for example, *Length Check XML v 1.0.0.0*) as a string parameter. Call `GetSettingFromSettingsGroup()` to set the `Enabled` property. This method requires the settings group object, the setting name (for example, *Enabled*), and the default value (for example, True) as parameters. # [C#](#tab/tabid-6) ```cs @@ -112,14 +106,11 @@ public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, ``` *** -Set the Property to the Values from the Settings Bundle --- - -The base class also provides the ```SaveToSettingsBundle``` method, which is required to physically store the value of the properties in the bundle of the **.sdlproj* file. +## Save Properties to the Settings Bundle -Here too, we create a settings group object based on ```ISettingsGroup``` by applying the ```GetSettingsGroup``` method to the settings bundle. +The base class provides the `SaveToSettingsBundle()` method to store property values in the bundle of the **.sdlproj* file. -Then we invoke the ```UpdateSettingInSettingsGroup``` method to save the settings into the physical representation. This method takes the settings group object, the setting name (string), the setting value, and the default value as parameters. +Create a settings group object based on `ISettingsGroup` by calling `GetSettingsGroup()` on the settings bundle. Call `UpdateSettingInSettingsGroup()` to save settings to the physical representation. This method accepts the settings group object, the setting name (string), the setting value, and the default value as parameters. # [C#](#tab/tabid-7) ```cs @@ -133,10 +124,9 @@ public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string *** -Putting it All Together --- +## Putting It All Together -The complete class should now look as shown below: +Your complete class now includes all required functionality: # [C#](#tab/tabid-8) ```cs @@ -150,16 +140,10 @@ using System.Windows.Forms; namespace Sdk.FileTypeSupport.Samples.XMLChecker { - /// - /// This class is used to actually store the settings to the settings bundle, which - /// is physically saved in an *.sdlproj or in an *.sdltpl file. - /// - public class VerifierSettings: FileTypeSettingsBase + public class VerifierSettings : FileTypeSettingsBase { - #region "Properties" bool _enable; - public bool Enable { get { return _enable; } @@ -169,77 +153,40 @@ namespace Sdk.FileTypeSupport.Samples.XMLChecker OnPropertyChanged("Enable"); } } - #endregion "Properties" - #region "Constructor" public VerifierSettings() { ResetToDefaults(); } - #endregion "Constructor" - - - - #region "OverrideMethods" - /// - /// Define the default value, which is Enabled, as the verification function should - /// be active by default. - /// - #region "ResetToDefaults" public override void ResetToDefaults() { Enable = true; } - #endregion - - /// - /// This method is used to load the setting from the settings bundle, - /// which is physically stored in an XML-compliant *.sdlproj or *.sdltpl file. - /// - /// - /// - #region "PopulateFromSettingsBundle" + public override void PopulateFromSettingsBundle(ISettingsBundle settingsBundle, string configurationId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(configurationId); ResetToDefaults(); Enable = GetSettingFromSettingsGroup(settingsGroup, "Enable", Enable); } - #endregion - - /// - /// This method is used to store the settings as configured in the plug-in UI - /// in the settings bundle, which means that the settings are physically written - /// into the XML-compliant *.sdlproj or *.sdltpl file. - /// - /// - /// - #region "SaveToSettingsBundle" + public override void SaveToSettingsBundle(ISettingsBundle settingsBundle, string configurationId) { ISettingsGroup settingsGroup = settingsBundle.GetSettingsGroup(configurationId); var defaults = new VerifierSettings(); UpdateSettingInSettingsGroup(settingsGroup, "Enable", Enable, defaults.Enable); } - #endregion - - #endregion "OverrideMethods" } } ``` *** -See Also --- - - - -[Implement the User Interface](implement_the_user_interface_native.md) - -[Implement the UI Controller Class](implement_the_ui_controller_class_native.md) +## See Also -[Implement the Verification Logic](implement_the_verification_logic_native.md) +- [Implement the User Interface](implement_the_user_interface_native.md) +- [Implement the UI Controller Class](implement_the_ui_controller_class_native.md) +- [Implement the Verification Logic](implement_the_verification_logic_native.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/locking_specific_strings.md b/apiconcepts/filetypesupport/locking_specific_strings.md index 2b7edce60b..1e80def7b3 100644 --- a/apiconcepts/filetypesupport/locking_specific_strings.md +++ b/apiconcepts/filetypesupport/locking_specific_strings.md @@ -1,47 +1,36 @@ -Locking Specific Strings -=== +# Locking Specific Strings -In this chapter you will learn how to protect text against editing by locking strings. +Protect text against editing by locking strings. -Locking Particular Strings During Parsing --- +## Locking Particular Strings During Parsing -Sometimes you may want to create segments, text selections, or paragraph units that are locked, i.e. whose content users cannot edit. This might be the case, for example, if a paragraph unit contains script code, which should not be altered or accidentally modified by the translator. However, translators should be able to view such strings, as they may contain relevant information, which assists during the translation process. +Create locked segments, text selections, or paragraph units to prevent user editing. Lock strings containing script code that should not be altered or modified during translation. Translators can still view locked content, which provides relevant information during the translation process. -Let us assume that our text files contain single lines that start with a product code prefix, e.g. *Prd-Code NCC1504*. If these strings must not be localized, you can lock them during parsing of the file. +For example, your text files might contain lines starting with a product code prefix, such as *Prd-Code NCC1504*. Lock these strings during parsing to prevent localization. -To do this enhance your file parser by adding a`` WriteLockedContent()`` helper function: +Enhance your file parser by adding a `WriteLockedContent()` helper function: # [C#](#tab/tabid-1) ```cs -// protect text from being altered during translation -// by locking it private void WriteLockedContent(string LockedContent) { - //create opening tag for locked content ILockedContentProperties Lockedprops = PropertiesFactory.CreateLockedContentProperties(LockTypeFlags.Manual); Output.LockedContentStart(Lockedprops); - //create text inside of locked content ITextProperties textProps = PropertiesFactory.CreateTextProperties(LockedContent); Output.Text(textProps); - //close locked content Output.LockedContentEnd(); } ``` *** -Here, the [CreateLockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentItemFactory.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentItemFactory_CreateLockedContent_Sdl_FileTypeSupport_Framework_NativeApi_ILockedContentProperties_) method is used to create a mark-up container that can wrap all the other containers and mark-up of a target paragraph in a paragraph unit. However, you must first create an [ILockedContentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ILockedContentProperties.yml) object by calling [CreateLockedContentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateLockedContentProperties_Sdl_FileTypeSupport_Framework_NativeApi_LockTypeFlags_) with a parameter of [LockTypeFlags](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml). Then, the resulting locked content properties can be passed to the [CreateLockedContentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateLockedContentProperties_Sdl_FileTypeSupport_Framework_NativeApi_LockTypeFlags_) method. Once an object derived from [ILockedContentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ILockedContentProperties.yml) object has been created, it can be used to wrap all the mark-up in the target paragraph of the paragraph unit. +The [CreateLockedContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IDocumentItemFactory.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentItemFactory_CreateLockedContent_Sdl_FileTypeSupport_Framework_NativeApi_ILockedContentProperties_) method creates a mark-up container that wraps all other containers and mark-up of a target paragraph in a paragraph unit. First, create an [ILockedContentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ILockedContentProperties.yml) object by calling [CreateLockedContentProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateLockedContentProperties_Sdl_FileTypeSupport_Framework_NativeApi_LockTypeFlags_) with a [LockTypeFlags](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml) parameter. Pass the resulting locked content properties to use for wrapping all mark-up in the target paragraph. -All you need to do in our example is to extend the ```ProcessLine()``` helper function to call ```WriteLockedContent()``` whenever a line that starts with a product code prefix has been found: +Extend the `ProcessLine()` helper function to call `WriteLockedContent()` whenever a line starts with a product code prefix: # [C#](#tab/tabid-2) ```cs -// determines whether a given line is -// translatable or not -// if not, a structure tag is output -// otherwise, the translatable text is exposed private void ProcessLine(string sLine) { if (sLine.StartsWith("[") && sLine.EndsWith("]")) @@ -52,7 +41,6 @@ private void ProcessLine(string sLine) else if (sLine.StartsWith("Prd-Code")) { WriteLockedContent(sLine); - } else { @@ -66,12 +54,11 @@ After making this enhancement to the file parser, the lines that contain product ![LockedContent](images/LockedContent.jpg) -Note that you may not be able to see the locked units in our example. If you do not see the locked content activate the **Display Filter** toolbar in Var:ProductName through the menu command **View** > **Toolbars** > **Display Filter**. Then choose **All content** from the **Display** dropdown list. +If you do not see the locked content, activate the **Display Filter** toolbar in Var:ProductName through **View** > **Toolbars** > **Display Filter**, then select **All content** from the **Display** dropdown. -Putting it All Together --- +## Putting It All Together -Your enhanced file parser should now look as shown below: +Your enhanced file parser now includes all the required functionality: # [C#](#tab/tabid-3) ```cs @@ -87,16 +74,10 @@ namespace Sdk.Snippets.Native { public class SimpleTextParser3 : AbstractNativeFileParser, INativeContentCycleAware { - #region "global settings" IPersistentFileConversionProperties _fileConversionProperties; StreamReader _reader = null; - FormattingGroup _fBold; - #endregion - #region "INativeContentCycleAware members" - // through the properties object you can retrieve important information - // on the native input file such as the original file name and path public void SetFileProperties(IFileProperties properties) { _fileConversionProperties = properties.FileConversionProperties; @@ -107,57 +88,34 @@ namespace Sdk.Snippets.Native } - public void EndOfInput() { } - #endregion - - #region "members of AbstractNativeFileParser" - #region "before parsing" protected override void BeforeParsing() { - // set progress reporter to the beginning OnProgress(0); - - // open the native input file for reading _reader = new StreamReader(_fileConversionProperties.OriginalFilePath); } - #endregion - #region "during parsing" protected override bool DuringParsing() { - // iterate through all lines in the input file while (!_reader.EndOfStream) { ProcessLine(_reader.ReadLine()); } return false; } - #endregion - #region "after parsing" protected override void AfterParsing() { - //close original file _reader.Close(); _reader.Dispose(); _reader = null; - //set progres report to 100% OnProgress(100); } - #endregion - - #endregion - #region "process line" - // determines whether a given line is - // translatable or not - // if not, a structure tag is output - // otherwise, the translatable text is exposed private void ProcessLine(string sLine) { if (sLine.StartsWith("[") && sLine.EndsWith("]")) @@ -168,55 +126,37 @@ namespace Sdk.Snippets.Native else if (sLine.StartsWith("Prd-Code")) { WriteLockedContent(sLine); - } else { WriteText(ProcessFormatting(sLine)); } } - #endregion - #region "text" - // output translatable text private void WriteText(string TextContent) { ITextProperties textProperties = PropertiesFactory.CreateTextProperties(TextContent); Output.Text(textProperties); } - #endregion - #region "lock" - // protect text from being altered during translation - // by locking it private void WriteLockedContent(string LockedContent) { - //create opening tag for locked content ILockedContentProperties Lockedprops = PropertiesFactory.CreateLockedContentProperties(LockTypeFlags.Manual); Output.LockedContentStart(Lockedprops); - //create text inside of locked content ITextProperties textProps = PropertiesFactory.CreateTextProperties(LockedContent); Output.Text(textProps); - //close locked content Output.LockedContentEnd(); } - #endregion - #region "structure" - // output non-translatable text as structure tag private void WriteStructureTag(string TagContent) { IStructureTagProperties structureTagProperties = PropertiesFactory.CreateStructureTagProperties(TagContent); structureTagProperties.DisplayText = TagContent; Output.StructureTag(structureTagProperties); } - #endregion - #region "context" - // output context information, not required, but useful - // information for the translator private void WriteContext(string ContextContent) { IContextProperties contextProperties = PropertiesFactory.CreateContextProperties(); @@ -228,12 +168,7 @@ namespace Sdk.Snippets.Native contextProperties.Contexts.Add(contextInfo); Output.ChangeContext(contextProperties); } - #endregion - #region "process formatting" - // this function uses regular expressions to identify - // what is 'normal' translatable content and which strings - // need to be marked up as inline tags, e.g. private string ProcessFormatting(string sLine) { int LastPosition = 0; @@ -255,12 +190,7 @@ namespace Sdk.Snippets.Native } return sLine.Substring(LastPosition, sLine.Length - LastPosition); } - #endregion - #region "write inline tag" - // this function outputs an opening or a closing tag - // and applies bold character formatting to the strings - // that the tags enclose private void WriteInlineTag(string tagContent, bool isStart) { _fBold = new FormattingGroup(); @@ -284,7 +214,6 @@ namespace Sdk.Snippets.Native Output.InlineEndTag(endTag); } } - #endregion } } ``` diff --git a/apiconcepts/filetypesupport/mapping_the_segment_confirmation_levels.md b/apiconcepts/filetypesupport/mapping_the_segment_confirmation_levels.md index 5fd96218a0..496bffa4b9 100644 --- a/apiconcepts/filetypesupport/mapping_the_segment_confirmation_levels.md +++ b/apiconcepts/filetypesupport/mapping_the_segment_confirmation_levels.md @@ -1,14 +1,12 @@ -Mapping the Segment Confirmation Levels -=== +# Mapping the Segment Confirmation Levels -In this chapter we will enhance our writer component to map the SDLXliff confirmation level values back to the BIL status values. +Enhance your writer component to map SDLXliff confirmation level values back to BIL status values. -Enhance the Writer Class to Update the Status Values --- +## Enhance the Writer Class to Update the Status Values -The parser component mapped the ```status``` attribute values of the BIL units to the corresponding confirmation levels that are used in SDLXliff (see [Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md)). The writer component needs to do the exact opposite. For example: in the original BIL file the status of a unit was *new*, as it did not have a target segment. In Var:ProductName the translation has been added and confirmed by the translator. Thus, the status should be 'upgraded' to exact. +The parser component maps the ```status``` attribute values of BIL units to the corresponding confirmation levels used in SDLXliff (see [Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md)). The writer component reverses this mapping. For example, a unit with status *new* (no target segment) receives a translation in Var:ProductName and the translator confirms it. The status updates to *exact*. -First, modify the ```CreateParagraphUnit()``` helper function to call a separate helper function, which returns the status value that was mapped from the paragraph unit confirmation value used in SDLXliff. Then, the status attribute of the current BIL ```unit``` element is changed to the string value returned by the ```UpdateStatus()``` helper function: +Modify the ```CreateParagraphUnit()``` helper function to call a separate helper function that returns the BIL status value mapped from the paragraph unit confirmation level. Update the status attribute of the XML ```unit``` element using the value returned by ```UpdateStatus()```: # [C#](#tab/tabid-1) ```cs @@ -17,19 +15,17 @@ private void CreateParagraphUnit(IParagraphUnit paragraphUnit, XmlNode xmlUnit) XmlNode source = xmlUnit.SelectSingleNode("source"); XmlNode target = xmlUnit.SelectSingleNode("target"); - //iterate all segment pairs foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) { source.InnerXml = _textExtractor.GetPlainText(segmentPair.Source); target.InnerXml = _textExtractor.GetPlainText(segmentPair.Target); - // update unit status xmlUnit.SelectSingleNode("./@status").Value = UpdateStatus(segmentPair.Properties.ConfirmationLevel); } } ``` *** -Now add the new ```UpdateStatus()``` helper function: +Add the ```UpdateStatus()``` helper function: # [C#](#tab/tabid-2) ```cs @@ -58,10 +54,9 @@ private string UpdateStatus(ConfirmationLevel unitLevel) ``` *** -Putting it All Together --- +## Putting It All Together -The enhanced writer class should now look as shown below: +Your enhanced writer class now includes all required functionality: # [C#](#tab/tabid-3) ```cs @@ -75,14 +70,11 @@ namespace Sdk.Snippets.Bilingual { class BilWriter3 : AbstractBilingualFileTypeComponent, IBilingualWriter, INativeOutputSettingsAware { - #region "global" private IPersistentFileConversionProperties _originalFileProperties; private INativeOutputFileProperties _nativeFileProperties; private XmlDocument _targetFile; private BilTextExtractor _textExtractor; - #endregion - #region "INativeOutputSettingsAware members" public void GetProposedOutputFileInfo(IPersistentFileConversionProperties fileProperties, IOutputFileInfo proposedFileInfo) { _originalFileProperties = fileProperties; @@ -92,57 +84,39 @@ namespace Sdk.Snippets.Bilingual { _nativeFileProperties = properties; } - #endregion - #region "IBilingualWriter members" - - - #region "load file" public void SetFileProperties(IFileProperties fileInfo) { _targetFile = new XmlDocument(); _targetFile.Load(_originalFileProperties.OriginalFilePath); } - #region "initialize" public void Initialize(IDocumentProperties documentInfo) { _textExtractor = new BilTextExtractor(); } - #endregion - - #endregion - #region "paragraphs" public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) { string unitId = paragraphUnit.Properties.Contexts.Contexts[1].GetMetaData("UnitID"); XmlNode xmlUnit = _targetFile.SelectSingleNode("//unit[@id='" + unitId + "']"); - - // call helper function to generate the paragraph unit CreateParagraphUnit(paragraphUnit, xmlUnit); } - #endregion - #region "create paragraph" private void CreateParagraphUnit(IParagraphUnit paragraphUnit, XmlNode xmlUnit) { XmlNode source = xmlUnit.SelectSingleNode("source"); XmlNode target = xmlUnit.SelectSingleNode("target"); - //iterate all segment pairs foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) { source.InnerXml = _textExtractor.GetPlainText(segmentPair.Source); target.InnerXml = _textExtractor.GetPlainText(segmentPair.Target); - // update unit status xmlUnit.SelectSingleNode("./@status").Value = UpdateStatus(segmentPair.Properties.ConfirmationLevel); } } - #endregion - #region "confirmation level" private string UpdateStatus(ConfirmationLevel unitLevel) { string status = ""; @@ -165,9 +139,7 @@ namespace Sdk.Snippets.Bilingual return status; } - #endregion - #region "save file and complete" public void FileComplete() { _targetFile.Save(_nativeFileProperties.OutputFilePath); @@ -178,29 +150,19 @@ namespace Sdk.Snippets.Bilingual { } - #endregion - - #endregion - - #region Implementation of IDisposable public void Dispose() { throw new NotImplementedException(); } - - #endregion } } ``` *** -See Also --- - - +## See Also -[Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md) +- [Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/merging_files.md b/apiconcepts/filetypesupport/merging_files.md index 71c6394c49..c39d6e3c60 100644 --- a/apiconcepts/filetypesupport/merging_files.md +++ b/apiconcepts/filetypesupport/merging_files.md @@ -1,22 +1,26 @@ -Merging files -===== -When creating projects that involve multiple files, users have the option of merging several files into one. This can facilitiate typical editing operations such as find/replace, document verification, etc. +# Merging files -During project creation, users can choose to merge several files into one intermediary (SDLXliff) document. Example: You want to generate a single intermediary document from 100 small XML documents. Handling only one file instead of 100 can faciliate common editing operations such as find/replace, QA check, etc. considerably, as these tasks can then be run on a single file rather than on multiple documents. +When you create a project with multiple source files, you can merge them into one intermediary SDLXliff document. This approach simplifies common tasks such as find and replace, verification, and QA checks. + +For example, instead of handling 100 small XML files separately, you can generate one intermediary document and run these tasks once on a single file. -Merging several native files of different formats into one intermediary (SDLXliff) document +Merging several native files of different formats into one intermediary SDLXliff document + +## Merge different native formats -Var:ProductName even allows you to merge different native file formats into one intermediary document (e.g. PPT, XLS, DOC, XML, etc.). In the editor of Var:ProductName markers indicate where a file ends and where the next file begins. Depending on where the user has currently positioned the cursor, a native preview is generated for that particular document (provided that the file type plug-in for that specific file format supports the generation of a preview). +Var:ProductName also lets you merge different native file formats into one intermediary document (for example, PPT, XLS, DOC, and XML). In the Var:ProductName editor, markers show where one file ends and the next begins. The editor generates a native preview for the document at the current cursor position, as long as that file type plug-in supports preview generation. Delimiters indicate where one file ends and where the next one begins -When the user generates the native documents, the intermediary file that was generated during the merge operation is split into the individual native target documents. (For example, when merging 10 PPT files, you will not generate one big PPT document, but one SDLXliff document.) +## Generate native target documents + +When you generate native documents, Var:ProductName splits the merged intermediary file into individual native target files. For example, if you merge 10 PPT files, you work with one SDLXliff document during translation and generate 10 separate PPT target documents. + +## See also -See Also --------- -[Creating projects](creating_projects.md) +- [Creating projects](creating_projects.md) diff --git a/apiconcepts/filetypesupport/moving_files_between_machines.md b/apiconcepts/filetypesupport/moving_files_between_machines.md index 28b19247f3..94086c7a47 100644 --- a/apiconcepts/filetypesupport/moving_files_between_machines.md +++ b/apiconcepts/filetypesupport/moving_files_between_machines.md @@ -1,13 +1,25 @@ -Moving files between machines -===== -More often than not, files are not translated, edited or proofread on the machine on which a project was originally created. For example, a project manager will usually send files to another user (e.g. a translator or proofreader) and then receive back the translated or edited file. +# Moving files between machines -Files can be moved between machines primarily in the two following ways: +Files are often translated, edited, or proofread on a different machine than the one where the project started. For example, a project manager may send files to a translator or proofreader and then receive the completed files back. -* A package is created from a project. A package is basically a ZIP file that contains the intermediary (SDLXliff) documents, file type settings, and optionally, additional resources such as reference files, TMs, termbases, AutoSuggest dictionaries, etc. The recipient of a package opens the package file, thus extracting its content to an empty folder on his/her disk. After opening the package, the package content can be processed in Var:ProductName, e.g. the translatable files are translated, edited, etc. After finishing the task, the recipent of the package creates a return package. The return package is also a ZIP file that contains the edited/translated intermediary documents. The return package is then sent to the person who created the project package, usually the project manager. +You can move files between machines in two ways: - +## Use a project package + +A project package is a ZIP file that contains the intermediary SDLXliff files, file type settings, and optional resources such as reference files, translation memories, termbases, and AutoSuggest dictionaries. + +1. Create a package from the project. +2. The recipient opens the package and extracts its contents to an empty folder. +3. The recipient processes the package content in Var:ProductName. +4. After completing the task, the recipient creates a return package. +5. The return package, which also contains the edited or translated intermediary files, goes back to the person who created the project package. + + **Wizard-based creation of a project package** -* Files may also be passed to another user/machine simply by passing the intermediary (SDLXliff) file, e.g. by sending it as an email attachment. In this case, you need to observe that simply passing the intermediary file will not include the file type setting file on which this particular intermediary document is based. +## Send the intermediary file directly + +You can also send the intermediary SDLXliff file directly, for example as an email attachment. + +This approach does not include the file type settings that were used to create the intermediary document. Use it only when you do not need to preserve those settings separately. diff --git a/apiconcepts/filetypesupport/native_file_tweakers.md b/apiconcepts/filetypesupport/native_file_tweakers.md index c86faedafe..336a9a7f37 100644 --- a/apiconcepts/filetypesupport/native_file_tweakers.md +++ b/apiconcepts/filetypesupport/native_file_tweakers.md @@ -1,21 +1,19 @@ -Native File Tweakers -=== +# Native File Tweakers -Native file tweakers are optional filter components, which allow additional processing to be performed on the input file before parsing begins or after the target file has been generated. +Native file tweakers are optional filter components that perform additional processing on the input file before parsing starts or on the target file after generation completes. -Native file tweakers should only be used in the rare cases, for example when the parsing mechanism does not allow for sufficient low-level access to the file details and it is therefore not possible to round-trip all required information. For example, The XML parser uses the .NET XmlReader, which performs it's own pre-processing on entities. This means that you cannot be certain in which form the entity was present in the original file. A file tweaker would then allow you to encode these entities before parsing so you can be certain of their original format. +Use native file tweakers only in rare cases. For example, you might need one when the parsing mechanism does not provide enough low-level access to preserve all required information during round-tripping. The .NET `XmlReader`, for example, performs its own preprocessing on entities. As a result, you cannot always determine the exact form of an entity in the original file. A file tweaker can encode those entities before parsing so that you can preserve their original format. -Using a Native File Pre-Tweaker --- +## Using a native file pre-tweaker -The following example demonstrates how to include a pre-tweaker in the extractor of a filter File Type Component Builder: +The following example shows how to add a pre-tweaker to the extractor in a filter File Type Component Builder: # [C#](#tab/tabid-1) ```cs /// /// Gets the file extractor for this component. /// /// not used here -/// a FileExtractor containing an Simple Text Parser +/// a FileExtractor containing a Simple Text Parser public virtual IFileExtractor BuildFileExtractor(string name) { var parser = new SimpleTextParser(); @@ -27,19 +25,18 @@ public virtual IFileExtractor BuildFileExtractor(string name) ``` *** -(SimpleFilePreTweaker is a class that implements [AbstractFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml)) +`SimpleFilePreTweaker` implements [AbstractFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml). -Using a Native File Post-Tweaker --- +## Using a native file post-tweaker -The following example demonstrates how to include a post-tweaker in the generator of a filter File Type Component Builder: +The following example shows how to add a post-tweaker to the generator in a filter File Type Component Builder: # [C#](#tab/tabid-2) ```cs /// /// Gets the file generator for this component. /// -/// not used herer +/// not used here /// Null if no file generator is defined public virtual IFileGenerator BuildFileGenerator(string name) { @@ -51,24 +48,17 @@ public virtual IFileGenerator BuildFileGenerator(string name) ``` *** -(SimpleFilePostTweaker is a class that implements [AbstractFilePostTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml)) - -See Also --- - -**Reference** - -[AbstractFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePreTweaker.yml) - -[AbstractFilePostTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml) +`SimpleFilePostTweaker` implements [AbstractFilePostTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.AbstractFilePostTweaker.yml). -[RegExFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.RegExFilePreTweaker.yml) +### Reference -[RegExFilePostTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.RegExFilePostTweaker.yml) +- [RegExFilePreTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.RegExFilePreTweaker.yml) +- [RegExFilePostTweaker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.RegExFilePostTweaker.yml) +## See also -[Creating a Native File Tweaker](creating_a_native_file_tweaker.md) +- [Creating a Native File Tweaker](creating_a_native_file_tweaker.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/opening_a_document_for_translation.md b/apiconcepts/filetypesupport/opening_a_document_for_translation.md index 1bfdc8aa76..4ddcb78865 100644 --- a/apiconcepts/filetypesupport/opening_a_document_for_translation.md +++ b/apiconcepts/filetypesupport/opening_a_document_for_translation.md @@ -1,44 +1,48 @@ -Opening a document for translation -===== -In Var:ProductName translators can open single documents for translation and editing. +# Opening a document for translation -When processing single documents, the file to translate is opened in Var:ProductName, e.g. a Microsoft Word (*.doc) document. In this step, the File Type Support Framework decides which file type plug-in best supports the given document format. +In Var:ProductName, translators open a single document for translation and editing. + +When they open a document, such as a Microsoft Word (*.doc) file, the File Type Support Framework selects the file type plug-in that best matches the format. -The user then sets the required source and target language and selects one or more translation memories (TM). Note that users are not required to select a TM. They can open and process the file in the editor of Var:ProductName without a TM. +The translator then selects the source and target languages. They can also select one or more translation memories (TM). If they do not need a TM, they can work directly in the Var:ProductName editor. -Conversion into the Intermediary Format ------- -In the background, an intermediary, bilingual file (e.g. SDLXliff) is generated from the native document. This step is called **extraction**, as the translatable content gets extracted and exposed for translation/editing purposes. The original native file can be embedded as a dependency file inside the intermediary file. This dependency might be required to generate the native target document from the intermediary file. This might be necessary, as native documents often contain elements such as images, diagrams, etc., which need to be included in the native target document. +# Convert the document to an intermediary format + +In the background, Var:ProductName creates an intermediary bilingual file, such as SDLXliff, from the native document. This step is called **extraction** because Var:ProductName pulls the translatable content out for translation. + +Var:ProductName can embed the original native file as a dependency inside the intermediary file. It may need that dependency later to generate the native target document, especially when the document contains images or diagrams that must appear in the final file. -The source and target content is presented in a side-by-side editor. The target content is entered (segment by segment) into the column on the right-hand side. The last column contains the so-called document structure information, which indicates whether a segment is e.g. a heading (**H**), a footnote (**FN**), etc. (see [Using Context Information](using_context_information.md)). The file type plug-in extracts localizable content for translation/editing. The editor view of Var:ProductName will also show any special elements as inline placeholder tags, for example footnote references, fields, index markers, etc. (see [Tag display modes](tag_display_modes.md)). Those elements have to be inserted into the target text by the translator, otherwise the corresponding footnote reference, field, etc. would be missing from the resulting target document. +The source and target content appears in a side-by-side editor. Translators enter the target text segment by segment in the right-hand column. The last column shows document structure information, which identifies headings (**H**) and footnotes (**FN**) (see [Using Context Information](using_context_information.md)). + +The file type plug-in also extracts localizable content and displays special elements as inline placeholder tags, such as footnote references, fields, and index markers (see [Tag display modes](tag_display_modes.md)). Translators must insert those elements into the target text so the final document keeps the correct references and structure. -During the translation process the document is saved in the intermediary bilingual format (e.g. SDLXliff). While the translation is in progress, all changes occur within the intermediary file, i.e. the native document stays untouched. +During translation, Var:ProductName saves all changes in the intermediary bilingual file, such as SDLXliff. The native document remains unchanged until generation. -Generating the Native Target File ------- -At the end of the translation phase, the translator uses a command such as **Save Target As** to generate the target-language version in the native document format. This last step is called **generation** (i.e. generation of the native target file). +# Generate the native target file + +At the end of translation, the translator uses a command such as **Save Target As** to generate the target-language version in the native document format. This last step is called **generation**. -See Also ------ -[Creating projects](creating_projects.md) +# See also + +- [Creating projects](creating_projects.md) -[File type settings](file_type_settings.md) +- [File type settings](file_type_settings.md) -[Using context information](using_context_information.md) +- [Using context information](using_context_information.md) -[Tag display modes](tag_display_modes.md) +- [Tag display modes](tag_display_modes.md) -[Saving to different file types](saving_to_different_file_types.md) +- [Saving to different file types](saving_to_different_file_types.md) -[Implementing the File Parser](implementing_the_file_parser.md) +- [Implementing the File Parser](implementing_the_file_parser.md) diff --git a/apiconcepts/filetypesupport/opening_the_file_for_parsing.md b/apiconcepts/filetypesupport/opening_the_file_for_parsing.md index 5aa3034a6d..fb164bc92a 100644 --- a/apiconcepts/filetypesupport/opening_the_file_for_parsing.md +++ b/apiconcepts/filetypesupport/opening_the_file_for_parsing.md @@ -1,27 +1,24 @@ -Opening the File for Parsing -=== +# Opening the File for Parsing -In this step you will learn how to implement the class that extracts translatable text from a given bilingual source (BIL) file. +Implement a class that extracts translatable text from a bilingual source (BIL) file. -Add the Parser Class --- +## Add the Parser Class -Start by adding a class called e.g. **BilParser1.cs** to your project. Your parser class needs to reference the following namespaces: +Create a class called **BilParser1.cs** in your project. Your parser class requires references to the following namespaces: * Sdl.FileTypeSupport.Framework.BilingualApi * Sdl.FileTypeSupport.Framework.NativeApi +* System.Xml -Bilingual files will often be XML-compliant, which makes parsing relatively easy, as you can leverage the standard XML DOM API. Therefore, you should also add the``` System.Xml``` namespace to your class. -Then, your parser needs to be derived from the following class and interfaces: +Bilingual files are typically XML-compliant, which simplifies parsing through the standard XML DOM API. Derive your parser from these classes and interfaces: * [AbstractBilingualFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualFileTypeComponent.yml) * [IBilingualParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualParser.yml) * [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) -Open and Close the Input File --- +## Open and Close the Input File -First, add the following global class members: +Add the following global class members: # [C#](#tab/tabid-1) ```cs @@ -31,10 +28,9 @@ public event EventHandler Progress; ``` *** -We require the ```_fileProperties``` object from which we can retrieve important information on a given input file, primarily the file path and name. We also require an XML document object (```_document```), which we can parse using the XML DOM API. It is recommended (but not required) that you implement a progress reporter event. Depending on the size of your input file, parsing may take time. Therefore it is useful to inform the end user of the file parsing progress by implementing a progress report mechanism. +The ```_fileProperties``` object retrieves important information about the input file, primarily the file path and name. An XML document object (```_document```) allows parsing using the XML DOM API. A progress reporter event is recommended (but not required) to inform users of parsing progress for large files. -Now you need to add the following members of the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) -interface: +Add the following members of the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface: # [C#](#tab/tabid-2) ```cs @@ -51,8 +47,9 @@ public void SetFileProperties(IFileProperties properties) ``` *** -The above member creates the object from which you can retrieve various items of information on the input file such as the file name, creation date, etc. It also initializes the ```DocumentProperties``` - used to create properties - and the output file properties. You may wonder why the parser initializes two distinct objects, i.e. a document and a file properties object. The reason for this is that the File Type Support Framework allows you to merge several files (e.g. several **.bil* documents) into a single SDLXliff file. In this case there would be a global document properties object for the SDLXliff master document and several file properties for the different files that have been merged into one intermediate (e.g. SDLXliff) file. -Then, add the following member, which the input file into the XML DOM object. At the same time, you can use this member to set the progress reporter to 0%: +This member creates objects to retrieve file information such as file name and creation date. It initializes the ```DocumentProperties``` used to create properties and output file properties. The parser initializes a document and a file properties object because the File Type Support Framework merges multiple files (e.g., **.bil* documents) into a single SDLXliff file. A global document properties object handles the SDLXliff master document, while separate file properties handle each merged file. + +Add the following member, which loads the input file into the XML DOM object and sets the progress reporter to 0%: # [C#](#tab/tabid-3) ```cs @@ -65,15 +62,13 @@ public void StartOfInput() ``` *** -The interface also requires you to add the following member, in which you implement the logic that should be applied when reaching the end of the input file. For example, you can set the XML DOM object to null and the progress reporter to 100%, as the file has been fully parsed. Since the plugin also uses an Output object, which is for example used by Studio to write .sdlxliff files, you also need to call the FileComplete and Complete functions of the writer, to properly finalize the created file. +Add the following member, which implements logic to apply when reaching the end of the input file. Set the XML DOM object to null, set the progress reporter to 100%, and call the FileComplete and Complete functions of the output object to finalize the file: # [C#](#tab/tabid-4) ```cs public void EndOfInput() { - // done with the file Output.FileComplete(); - // done with the document Output.Complete(); OnProgress(100); @@ -82,7 +77,7 @@ public void EndOfInput() ``` *** -Next, add the following (optional) ```OnProgress()``` method, which takes a byte parameter to set the progress within the range of 0 and 100%: +Add the following optional ```OnProgress()``` method, which takes a byte parameter to report parsing progress from 0 to 100%: # [C#](#tab/tabid-5) ```cs @@ -96,8 +91,7 @@ protected virtual void OnProgress(byte percent) ``` *** -Add the Bilingual Parser Members --- +## Add the Bilingual Parser Members Add the following required members of the bilingual parser interface: @@ -117,13 +111,11 @@ public IBilingualContentHandler Output ``` *** -The document properties member provides access to important information on the bilingual (i.e. not the native) file, e.g. the source and target language, the source segment count, the path to which the document was last saved, etc. -The output member handles the output to the bilingual document. Through this member you will later determine the paragraphs, segment pairs, etc. that are written to the bilingual file. +The ```DocumentProperties``` member provides access to information about the bilingual file, such as source and target language, source segment count, and save path. The ```Output``` member handles output to the bilingual document and determines paragraphs, segment pairs, and other content written to the bilingual file. -Parse the File --- +## Parse the File -Add the following member, which takes care of the actual file parsing operation. Note that no actual file content is parsed for the moment. We will implement the logic for parsing the file content later by adding helper functions to our parser component. +Add the following member, which handles the actual file parsing operation. File content parsing is deferred to helper functions added later: # [C#](#tab/tabid-7) ```cs @@ -134,16 +126,15 @@ public bool ParseNext() ``` *** -At this point you could already build your project, however, your file type plug-in will only generate an empty bilingual document, which would look in Var:ProductName as shown below: +Your project compiles at this point, but generates an empty bilingual document in Var:ProductName: ![EmptyBilFile](images/EmptyBilFile.jpg) -The resulting intermediary (SDLXliff) file would merely contain the basic header information that was retrieved from the document and file properties objects such as the original file name, the source/target language, the File Type Support Framework version, etc. +The intermediate SDLXliff file contains only basic header information from the document and file properties objects: original file name, source/target language, File Type Support Framework version, and similar metadata. -Add the Component Reference to the Component Builder --- +## Add the Component Reference to the Component Builder -Do not forget to add the parser component to the File Type Component Builder by inserting the following code to your implementation of the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) interface. Remember that failure to do so will mean that this component will never be used by the file type plug-in, even if the parser has been implemented in the assembly. +Add the parser component to the File Type Component Builder by implementing the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) interface. Failure to do so prevents the file type plug-in from using this component, even if the parser is in the assembly: # [C#](#tab/tabid-8) ```cs @@ -154,29 +145,17 @@ public IFileExtractor BuildFileExtractor(string name) return extractor; } ``` -** - -See Also --- - - - -[Outputting Segment Pairs](outputting_segment_pairs.md) - -[Processing Inline Tags](processing_inline_tags.md) - -[Applying Character Formatting](applying_character_formatting.md) - -[Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md) - -[Adding Context Information](adding_context_information.md) - -[Extracting Comments](extracting_comments.md) - -[Putting it all Together](putting_it_all_together.md) -[Merging files](merging_files.md) +## See Also +- [Outputting Segment Pairs](outputting_segment_pairs.md) +- [Processing Inline Tags](processing_inline_tags.md) +- [Applying Character Formatting](applying_character_formatting.md) +- [Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md) +- [Adding Context Information](adding_context_information.md) +- [Extracting Comments](extracting_comments.md) +- [Putting it all Together](putting_it_all_together.md) +- [Merging files](merging_files.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/outputting_all_comments.md b/apiconcepts/filetypesupport/outputting_all_comments.md index e2441a58c2..bab5d83838 100644 --- a/apiconcepts/filetypesupport/outputting_all_comments.md +++ b/apiconcepts/filetypesupport/outputting_all_comments.md @@ -1,25 +1,22 @@ -Outputting all Comments -=== +# Outputting All Comments -In this chapter we will finalize the writer class by making it write any comments attached to the units of the original BIL file as well as any comments that were added to the target segments during translation in Var:ProductName. +Finalize the writer class to write comments attached to units in the original BIL file and comments added to target segments during translation in Var:ProductName. -About Comments --- +## About Comments -According to the specifications of our fictitious BIL format (see [About the Example BIL Format](about_the_example_bil_format.md)) a unit element may include one or more ```comment``` elements, each of which has its own id. +According to the BIL format specification (see [About the Example BIL Format](about_the_example_bil_format.md)), unit elements include one or more ```comment``` elements, each with its own id. -In Var:ProductName translators can add comments to target segments. The commented strings are then highlighted with a specific background colour. The comment text is visible, for example, when the user moves the mouse pointer over the commented string (see illustration below). +In Var:ProductName, translators add comments to target segments. The commented strings highlight with a specific background color. Comment text appears when users move the mouse pointer over the commented string (see illustration below). ![Comment](images/Comment.jpg) -In a BIL file comments are attached to the ```unit``` elements. This is where we will add any comments found in a segment pair when generating the native target file. +BIL file comments attach to ```unit``` elements. When generating the native target file, add any comments found in a segment pair to these units. -Extend the Text Extractor Class --- +## Extend the Text Extractor Class -When we implemented the ```BilTextExtractor``` class (see [Adding the Text Extractor Class](adding_the_text_extractor_class.md)) we did not process any comments attached to the segments. We want to change this behavior by making the following additions to this class. As a unit might contain more than one comment, you should create a global string list object. Then add a ```GetSegmentComment()``` helper function. This function first clears the comments list, and then calls the 'visitor' members to collect the required information from a given segment. Note that this function will later be called through the writer class. +When implementing the ```BilTextExtractor``` class (see [Adding the Text Extractor Class](adding_the_text_extractor_class.md)), comment processing was not included. Add a global string list object and a ```GetSegmentComment()``` helper function. This function clears the comments list, then calls visitor members to collect information from a given segment. The writer class calls this function later. -The [VisitCommentMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitCommentMarker_Sdl_FileTypeSupport_Framework_BilingualApi_ICommentMarker_) member, which we originally left empty, should look as shown below: +The [VisitCommentMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IMarkupDataVisitor_VisitCommentMarker_Sdl_FileTypeSupport_Framework_BilingualApi_ICommentMarker_) member visits segments and adds any found comments to the comments list: # [C#](#tab/tabid-1) ```cs @@ -32,38 +29,30 @@ public void VisitCommentMarker(ICommentMarker commentMarker) VisitChildren(commentMarker); } ``` -*** -This member actually 'visits' the segments and adds any comments found to our comments string list. +## Enhance the Writer Class - -Enhance the Writer Class --- - -Now we need to make some additions to our writer class. Start by adding yet another helper function called, e.g. ```UpdateComments()```. This helper function needs to be invoked from ```CreateParagraphUnit()``` and takes the current paragraph unit and the ```unit``` XML node as parameters, i.e.: +Add a helper function called ```UpdateComments()``` to the writer class. Invoke this function from ```CreateParagraphUnit()```, passing the current paragraph unit and XML ```unit``` node: # [C#](#tab/tabid-2) ```cs UpdateComments(paragraphUnit, xmlUnit); ``` -*** -The ```UpdateComments()``` helper function first 'wipes the slate clean' by removing any existing comments from the original BIL file: +The ```UpdateComments()``` helper function first removes any existing comments from the original BIL file: # [C#](#tab/tabid-3) ```cs -// clear the original comments XmlNodeList comments = unitNode.SelectNodes("comment"); foreach (XmlNode item in comments) { ((XmlElement)unitNode).RemoveChild(item); } ``` -*** -Now we need to compile a consolidated list of all comments (from the original BIL file) and of those comments that were added by the translator. Remember that each ```comment``` element in the BIL file requires an id, which we assign through a ```commentID``` integer variable. +Create a consolidated list of all comments from the original BIL file and comments added by the translator. Each ```comment``` element in the BIL file requires an id, assigned through a ```commentID``` integer variable. -First, we retrieve the comments that we added from the original BIL file and that are attached to the paragraph units: +Retrieve comments added from the original BIL file and attached to the paragraph units: # [C#](#tab/tabid-4) ```cs @@ -78,9 +67,8 @@ if (paragraphUnit.Properties.Comments != null) } } ``` -*** -Next, we collect the comments that the translator added in the intermediary (SDLXliff) file to the target segments. Note that we invoke the corresponding function from our ```BilTextExtractor``` class, which 'visits' the markup elements found within a segment. +Next, collect comments the translator added in the intermediate SDLXliff file to target segments. Invoke the corresponding function from the ```BilTextExtractor``` class, which visits markup elements within a segment: # [C#](#tab/tabid-5) ```cs @@ -93,28 +81,19 @@ foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) } } ``` -*** -The complete helper function looks as shown below: +The complete ```UpdateComments()``` helper function consolidates all comments: # [C#](#tab/tabid-6) ```cs private void UpdateComments(IParagraphUnit paragraphUnit, XmlNode unitNode) { - #region "clear" - // clear the original comments XmlNodeList comments = unitNode.SelectNodes("comment"); foreach (XmlNode item in comments) { ((XmlElement)unitNode).RemoveChild(item); } - #endregion - - // loop through the comments in the SDLXLIFF paragraph units (if available) - // these comments were added from the original BIL file - // during parsing (i.e. forward conversion) - #region "original comments" int commentID = 1; if (paragraphUnit.Properties.Comments != null) { @@ -125,12 +104,7 @@ private void UpdateComments(IParagraphUnit paragraphUnit, XmlNode unitNode) commentID++; } } - #endregion - - // generate the consolidated list of comments from the original - // BIL file and any comments added by the translator in the SDLXLIFF file - #region "tranlator comments" foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) { foreach (string comment in _textExtractor.GetSegmentComment(segmentPair.Target)) @@ -139,12 +113,10 @@ private void UpdateComments(IParagraphUnit paragraphUnit, XmlNode unitNode) commentID++; } } - #endregion } ``` -*** -Note that the above ```UpdateComments()``` function calls a separate ```AddComment()``` helper function, which generates the actual comment based on the comment text and the comment id, which is then added to the current ```unit``` element of the target BIL file. This helper function looks as shown below: +The ```UpdateComments()``` function calls the ```AddComment()``` helper function, which creates a comment element based on the comment text and comment id, then adds it to the current ```unit``` element of the target BIL file: # [C#](#tab/tabid-7) ```cs @@ -158,12 +130,10 @@ private void AddComment(XmlNode xmlUnit, string commentText, int commentID) xmlUnit.AppendChild(commentElement); } ``` -*** -Putting it All Together --- +## Putting It All Together -The complete and finished writer class should now look as shown below: +Your complete and finished writer class now includes all required functionality: # [C#](#tab/tabid-8) ```cs using System; @@ -179,14 +149,11 @@ namespace Sdk.FileTypeSupport.Samples.Bil { class BilWriter : AbstractBilingualFileTypeComponent, IBilingualWriter, INativeOutputSettingsAware { - #region "global" private IPersistentFileConversionProperties _originalFileProperties; private INativeOutputFileProperties _nativeFileProperties; private XmlDocument _targetFile; private BilTextExtractor _textExtractor; - #endregion - #region "INativeOutputSettingsAware members" public void GetProposedOutputFileInfo(IPersistentFileConversionProperties fileProperties, IOutputFileInfo proposedFileInfo) { _originalFileProperties = fileProperties; @@ -196,62 +163,40 @@ namespace Sdk.FileTypeSupport.Samples.Bil { _nativeFileProperties = properties; } - #endregion - - - #region "IBilingualWriter members" - - #region "load file" public void SetFileProperties(IFileProperties fileInfo) { _targetFile = new XmlDocument(); _targetFile.Load(_originalFileProperties.OriginalFilePath); } - #region "initialize" public void Initialize(IDocumentProperties documentInfo) { _textExtractor = new BilTextExtractor(); } - #endregion - #endregion - - #region "paragraphs" public void ProcessParagraphUnit(IParagraphUnit paragraphUnit) { - //old: string unitId = paragraphUnit.Properties.Contexts.Contexts[1].MetaData["UnitID"]; string unitId = paragraphUnit.Properties.Contexts.Contexts[1].GetMetaData("UnitID"); XmlNode xmlUnit = _targetFile.SelectSingleNode("//unit[@id='" + unitId + "']"); - // call helper function to generate the paragraph unit CreateParagraphUnit(paragraphUnit, xmlUnit); - // call helper function to consolidate all comments UpdateComments(paragraphUnit, xmlUnit); } - #endregion - - #region "helper functions" - #region "create paragraph" private void CreateParagraphUnit(IParagraphUnit paragraphUnit, XmlNode xmlUnit) { XmlNode source = xmlUnit.SelectSingleNode("source"); XmlNode target = xmlUnit.SelectSingleNode("target"); - // iterate all segment pairs foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) { source.InnerXml = _textExtractor.GetPlainText(segmentPair.Source); target.InnerXml = _textExtractor.GetPlainText(segmentPair.Target); - // update unit status xmlUnit.SelectSingleNode("./@status").Value = UpdateStatus(segmentPair.Properties.ConfirmationLevel); } } - #endregion - #region "confirmation level" private string UpdateStatus(ConfirmationLevel unitLevel) { string status = ""; @@ -274,25 +219,15 @@ namespace Sdk.FileTypeSupport.Samples.Bil return status; } - #endregion - #region "update comments" private void UpdateComments(IParagraphUnit paragraphUnit, XmlNode unitNode) { - #region "clear" - // clear the original comments XmlNodeList comments = unitNode.SelectNodes("comment"); foreach (XmlNode item in comments) { ((XmlElement)unitNode).RemoveChild(item); } - #endregion - - // loop through the comments in the SDLXLIFF paragraph units (if available) - // these comments were added from the original BIL file - // during parsing (i.e. forward conversion) - #region "original comments" int commentID = 1; if (paragraphUnit.Properties.Comments != null) { @@ -303,12 +238,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil commentID++; } } - #endregion - - // generate the consolidated list of comments from the original - // BIL file and any comments added by the translator in the SDLXLIFF file - #region "tranlator comments" foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs) { foreach (string comment in _textExtractor.GetSegmentComment(segmentPair.Target)) @@ -317,11 +247,8 @@ namespace Sdk.FileTypeSupport.Samples.Bil commentID++; } } - #endregion } - #endregion - #region "add comment" private void AddComment(XmlNode xmlUnit, string commentText, int commentID) { XmlElement commentElement = _targetFile.CreateElement("comment"); @@ -331,9 +258,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil commentElement.InnerText = commentText; xmlUnit.AppendChild(commentElement); } - #endregion - #region "save file and complete" public void FileComplete() { _targetFile.Save(_nativeFileProperties.OutputFilePath); @@ -344,25 +269,15 @@ namespace Sdk.FileTypeSupport.Samples.Bil { } - #endregion - #endregion - - #endregion - - #region IDisposable implementation public void Dispose() { - //don't need to dispose of anthing } - - #endregion } } ``` -*** -Below you also see the complete and finished text extractor class: +Your complete and finished text extractor class now includes all required functionality: # [C#](#tab/tabid-9) ```cs using System; @@ -375,7 +290,6 @@ namespace Sdk.FileTypeSupport.Samples.Bil { class BilTextExtractor : IMarkupDataVisitor { - #region "comment list" private List _Comments = new List(); public List GetSegmentComment(ISegment segment) @@ -384,9 +298,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil VisitChildren(segment); return _Comments; } - #endregion - #region "plain text" internal StringBuilder PlainText { get; @@ -399,10 +311,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil VisitChildren(segment); return PlainText.ToString(); } - #endregion - // loops through all sub items of the container (IMarkupDataContainer) - #region "loop" private void VisitChildren(IAbstractMarkupDataContainer container) { foreach (var item in container) @@ -410,28 +319,19 @@ namespace Sdk.FileTypeSupport.Samples.Bil item.AcceptVisitor(this); } } - #endregion - #region IMarkupDataVisitor Members - - #region "text" public void VisitText(IText text) { PlainText.Append(text.Properties.Text); } - #endregion - #region "tagpairs" public void VisitTagPair(ITagPair tagPair) { PlainText.Append("<" + tagPair.StartTagProperties.TagContent + ">"); VisitChildren(tagPair); PlainText.Append(""); } - #endregion - - #region "comments" public void VisitCommentMarker(ICommentMarker commentMarker) { for (int i = 0; i < commentMarker.Comments.Count; i++) @@ -440,9 +340,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil } VisitChildren(commentMarker); } - #endregion - #region "left empty" public void VisitSegment(ISegment segment) { VisitChildren(segment); @@ -450,47 +348,34 @@ namespace Sdk.FileTypeSupport.Samples.Bil public void VisitLocationMarker(ILocationMarker location) { - } public void VisitLockedContent(ILockedContent lockedContent) { - } public void VisitOtherMarker(IOtherMarker marker) { - } public void VisitPlaceholderTag(IPlaceholderTag tag) { - } public void VisitRevisionMarker(IRevisionMarker revisionMarker) { - } - #endregion - - #endregion } } ``` -*** - -See Also --- - +## See Also -[Extracting Comments](extracting_comments.md) - -[Adding the File Writer Class](adding_the_file_writer_class.md) - -[Adding the Text Extractor Class](adding_the_text_extractor_class.md) +- [Extracting Comments](extracting_comments.md) +- [Adding the File Writer Class](adding_the_file_writer_class.md) +- [Adding the Text Extractor Class](adding_the_text_extractor_class.md) >[!NOTE] > > This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. + diff --git a/apiconcepts/filetypesupport/outputting_segment_pairs.md b/apiconcepts/filetypesupport/outputting_segment_pairs.md index 47a0206a07..64e68a6f7e 100644 --- a/apiconcepts/filetypesupport/outputting_segment_pairs.md +++ b/apiconcepts/filetypesupport/outputting_segment_pairs.md @@ -1,14 +1,12 @@ -Outputting Segment Pairs -=== +# Outputting Segment Pairs -In this chapter you will learn how to extract and expose the source and target segments of a given BIL input file in the intermediary (SDLXliff) file, and thus in the editing environment of Var:ProductName. +Extract and expose source and target segments from a BIL input file in the intermediary SDLXliff file for editing in Var:ProductName. -Extend the Parsing Method --- +## Extend the Parsing Method -Now we need to extend the parsing logic to extract the source and target segments and expose them for translation in the editor of Var:ProductName. Basically, our parser should work like this: the content of a unit element defines a paragraph unit in the intermediary (SDLXliff) file. A unit element in a BIL file always contains one source segment and one or no target segment. These segments will be added to the paragraph unit as segment pairs. A segment pair must contain a source segment, but the target segment may be empty, i.e. in this case the target of the BIL unit element is empty. +Extend the parsing logic to extract source and target segments and expose them for translation in Var:ProductName's editor. A unit element defines a paragraph unit in the SDLXliff file. Each unit contains one source segment and optionally a target segment. These segments are added to the paragraph unit as segment pairs. A segment pair requires a source segment; the target segment may be empty. -Note that in this first step we are not going to process inline tags, formatting or any of the other elements a unit may contain (e.g. comments). +Note: This step does not process inline tags, formatting, or other unit elements (e.g., comments). Add the following ```foreach``` loop to the [ParseNext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualParser.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualParser_ParseNext) method: @@ -19,93 +17,73 @@ foreach (XmlNode item in _document.SelectNodes("//unit")) Output.ProcessParagraphUnit(CreateParagraphUnit(item)); } ``` -*** -This loop iterates through all ```unit``` elements of the input BIL file and outputs a paragraph unit in the intermediary (SDLXliff) document by calling a separate ```CreateParagraphUnit()``` helper function. This helper function takes the sub-nodes of the ```unit``` element as parameter. The sub-nodes in the current basic implementation will be, the ```source``` and ```target``` nodes. +This loop iterates through all ```unit``` elements in the input BIL file and outputs a paragraph unit in the SDLXliff document by calling the ```CreateParagraphUnit()``` helper function. This function takes the unit node's sub-nodes as parameters: the ```source``` and ```target``` nodes. -Add a Helper Function for Generating Paragraph Units --- +## Add a Helper Function for Generating Paragraph Units -In the next step add the helper function that is used to generate a paragraph unit from the current unit node. In this function you generate a paragraph unit object through the item factory as shown below: +Add the helper function to generate a paragraph unit from the current unit node. Create a paragraph unit object through the item factory: # [C#](#tab/tabid-2) ```cs IParagraphUnit paragraphUnit = ItemFactory.CreateParagraphUnit(LockTypeFlags.Unlocked); ``` -*** +The [LockTypeFlags](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml) parameter determines whether a paragraph unit is locked for editing. Normally, paragraph units remain unlocked, allowing translator access and editing. -Through the [LockTypeFlags](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LockTypeFlags.yml) parameter of the ```CreateParagraphUnit()``` helper function you can determine whether a paragraph unit should be locked for editing or not. Normally, the paragraph units will not be locked, which means that they can be accessed and edited by the translator. - -Now you use the item factory to create a segment pair object as shown below: +Create a segment pair object through the item factory: # [C#](#tab/tabid-3) ```cs ISegmentPairProperties segmentPairProperties = ItemFactory.CreateSegmentPairProperties(); ``` -*** -Next, you create a source segment object, which is then attached to the paragraph unit. If a target segment is available, you also need to create a target segment object and attach it to the paragraph unit. Below you see the full helper function for generating the paragraph unit object to output in the document. Note that the actual source and target segment generation occurs in a separate helper function, which we will create in the next step. +Create source and target segment objects and attach them to the paragraph unit. Below is the complete helper function for generating the paragraph unit object. Actual source and target segment generation occurs in a separate helper function, created in the next step. # [C#](#tab/tabid-4) ```cs -// helper function for creating paragraph units private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) { - // create paragraph unit object IParagraphUnit paragraphUnit = ItemFactory.CreateParagraphUnit(LockTypeFlags.Unlocked); + ISegmentPairProperties segmentPairProperties = ItemFactory.CreateSegmentPairProperties(); + segmentPairProperties.ConfirmationLevel = CreateConfirmationLevel(xmlUnit.Attributes["status"].Value); - // create segment pair object - ISegmentPairProperties segmentPairProperties = ItemFactory.CreateSegmentPairProperties(); - // assign the appropriate confirmation level to the segment pair - segmentPairProperties.ConfirmationLevel=CreateConfirmationLevel(xmlUnit.Attributes["status"].Value); - - // add source segment to paragraph unit - ISegment srcSegment = CreateSegment(xmlUnit.SelectSingleNode("source/seg"), segmentPairProperties); + ISegment srcSegment = CreateSegment(xmlUnit.SelectSingleNode("source/seg"), segmentPairProperties); paragraphUnit.Source.Add(srcSegment); - // add target segment to paragraph unit if available - if(xmlUnit.SelectSingleNode("target/seg") != null) + if (xmlUnit.SelectSingleNode("target/seg") != null) { ISegment trgSegment = CreateSegment(xmlUnit.SelectSingleNode("target/seg"), segmentPairProperties); paragraphUnit.Target.Add(trgSegment); } - #region "context" - // create paragraph unit context string id = xmlUnit.SelectSingleNode("./@id").InnerText; - if(xmlUnit.SelectSingleNode("type/@spec")!=null) + if (xmlUnit.SelectSingleNode("type/@spec") != null) { string spec = xmlUnit.SelectSingleNode("type/@spec").InnerText; - - paragraphUnit.Properties.Contexts=CreateContext(spec, id); - } else { + paragraphUnit.Properties.Contexts = CreateContext(spec, id); + } + else + { paragraphUnit.Properties.Contexts = CreateContext("Paragraph", id); } - #endregion - #region "comments" - // extract comment (if applicable) - if(xmlUnit.SelectSingleNode("comment")!=null) + if (xmlUnit.SelectSingleNode("comment") != null) { paragraphUnit.Properties.Comments = CreateComment(xmlUnit.SelectSingleNode("comment").InnerText); } - #endregion return paragraphUnit; } ``` -*** -Add a Helper Function for Generating the Source and Target Segments --- +## Add a Helper Function for Generating Source and Target Segments -The helper function that creates the source and target segments requires the segment node and the segment pair properties as parameters. Passing the segment pair properties makes certain that the source and target segments are assigned to the correct segment pair. This helper function uses the properties factory to generate the text properties from the text content of the seg node. Through the item factory you create the actual text object from the text properties. Last, the text is added to the segment object, which is then returned to the helper function. +The helper function that creates source and target segments requires the segment node and segment pair properties as parameters. Passing segment pair properties ensures source and target segments assign to the correct segment pair. This function uses the properties factory to generate text properties from the segment node's text content, creates the text object through the item factory, adds the text to the segment object, and returns it: # [C#](#tab/tabid-5) ```cs -// helper function for creating segment objects private ISegment CreateSegment(XmlNode segNode, ISegmentPairProperties pair) { ISegment segment = ItemFactory.CreateSegment(pair); @@ -125,30 +103,25 @@ private ISegment CreateSegment(XmlNode segNode, ISegmentPairProperties pair) return segment; } ``` -*** -If you build your project at this stage, your file type plug-in should yield the following result when opening the sample file: +Your file type plug-in produces the following result when opening the sample file at this stage: ![BilText](images/BilText.jpg) +## Update the Progress Count -Update the Progress Count --- - -At this point it is a good idea to implement the logic required for updating the progress report by making the following additions to the [ParseNext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualParser.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualParser_ParseNext) method: +Implement logic for updating the progress report by adding the following to the [ParseNext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualParser.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualParser_ParseNext) method: # [C#](#tab/tabid-6) ```cs public bool ParseNext() { - // variables for the progress report int totalUnitCount = _document.SelectNodes("//unit").Count; int currentUnitCount = 0; foreach (XmlNode item in _document.SelectNodes("//unit")) { Output.ProcessParagraphUnit(CreateParagraphUnit(item)); - // update the progress report currentUnitCount++; OnProgress(Convert.ToByte(Math.Round(100 * ((decimal)currentUnitCount / totalUnitCount), 0))); } @@ -156,20 +129,13 @@ public bool ParseNext() return false; } ``` -*** - -See Also --- - - - -[Processing Inline Tags](processing_inline_tags.md) - -[Applying Character Formatting](applying_character_formatting.md) -[Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md) +## See Also -[Adding Context Information](adding_context_information.md) +- [Processing Inline Tags](processing_inline_tags.md) +- [Applying Character Formatting](applying_character_formatting.md) +- [Applying the Segment Pair Confirmation Levels](applying_the_segment_pair_confirmation_levels.md) +- [Adding Context Information](adding_context_information.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/overview.md b/apiconcepts/filetypesupport/overview.md index a12ca011b2..198e05a58b 100644 --- a/apiconcepts/filetypesupport/overview.md +++ b/apiconcepts/filetypesupport/overview.md @@ -1,32 +1,50 @@ -File Type Support -===== -The File Type Support Framework enables translators to process a variety of different document formats (e.g. Microsoft Office, Adobe InDesign, etc.) consistently within the same translation environment. +# File Type Support -File Type Support in a Nutshell ----- -There are countless document formats that may require localization, e.g. HTML, XML, Adobe FrameMaker, etc. It would be rather inefficient if translators had to do the translation in the respective native editing environment (e.g. Adobe FrameMaker, QuarkXPress, InDesign, etc.) Ideally, translators should not require e.g. Adobe FrameMaker proper for the translation of FrameMaker files. Instead, Translators would rather work in a dedicated editing environment that offers translator-specific features such as lookup functionality in translation memories, termbases, quality assurance features, etc. +The File Type Support Framework lets translators process many document formats, such as Microsoft Office and Adobe InDesign, in a consistent translation environment. -The File Type Support Framework can be extended with additional file type plug-ins that extract translatable text from a given document format and generate an intermediary, 'translator-friendly' format from the native document, which is then opened and processed in the translation environment, i.e. Var:ProductName. This step is called extraction. The translation is then done in this intermediary format. Var:ProductName currently uses an XML-based format, which is compliant with the OASIS XLIFF standard and is called SDLXliff. Note that although Var:ProductName uses SDLXliff, the File Type Support Framework was designed to handle alternative intermediary formats. In the future, other options may become available. The intermediary SDLXliff format is bilingual, i.e. it stores both the source and the target content, which allows for easy comparison between source and target segments. This approach has the following advantages: +## File Type Support in a Nutshell -* All document formats can be processed in the same way, in the same application, and using the same workflows. -* Content is effectively separated from layout. The risk of adversely affecting the layout during localization is thereby minimized. -* Translators do not require the native application (e.g. Adobe FrameMaker) to localize a given document format, nor do they require any associated resources such as specific fonts. -After translation, a target-language version of the original native format is generated from the intermediary (SDLXliff) document, as the recipient of the translation (usually the customer) needs to have the target text in the native document format (e.g. Word, PowerPoint, etc.). This step is called generation (of the native target file). The original native file is often embedded within the intermediary (SDLXliff) document as a dependency file. The original file maybe required for the generation of the target document, as it often contains information other than text, such as pixel graphics, diagrams, etc., which need to be re-inserted into the native target file. (This is not the case for pure text formats, e.g. delimited text, HTML, etc.) +Many localization workflows involve formats such as HTML, XML, and Adobe FrameMaker. Translating these files in their native authoring tools slows the process and increases the risk of errors. Instead, translators work in a dedicated environment that provides translation memories, termbases, and quality assurance features. -**A DOC file that was opened in Microsoft Word properly:** +The File Type Support Framework uses file type plug-ins to extract translatable content from a source document and convert it into an intermediary format that Var:ProductName can open and process. This extraction step produces SDLXliff, an XML-based format that follows the OASIS XLIFF standard. The framework also supports alternative intermediary formats. - +SDLXliff stores both source and target content, which makes it easy to compare segments. This approach offers several benefits: +* It processes different document formats with the same application and workflow. +* It separates content from layout, which reduces the risk of layout damage during localization. +* It removes the need for the native authoring application and related resources, such as specific fonts. -**The same DOC file in the side-by-side editor of Var:ProductName. An intermediary SDLXliff file has been generated from the DOC file.** +The following images show the same DOC file in the native application and in the side-by-side editor in Var:ProductName. - +![A DOC file opened in Microsoft Word](images/NativeView.jpg) -Upon opening a native file, the File Type Support Framework 'decides' which one of the available file type plug-ins is best suited to process the given file format. Various criteria can be used to make this determination, primarily the file name extension, but also other criteria, e.g. information that is available in the header of the native document. - Var:ProductName is delivered with a range of file type plug-ins. The File Type Support Framework, however, is flexible and extensible, and can therefore be extended with custom plug-ins for other formats. +![The same DOC file in the side-by-side editor of Var:ProductName](images/AbstractView.jpg) -The File Type Support Framework was designed to process both native, monolingual documents (e.g. Microsoft Word) and bilingual formats, e.g. TTX (i.e. TradosTag from Trados 2007), ITD (from SDLX 2007), etc. +After translation, the framework generates the target-language version of the original native format from the intermediary document. This step reuses the original file as a dependency when the target format needs non-text content, such as graphics or diagrams. Pure text formats, such as delimited text and HTML, do not require this dependency. -The file type plug-ins that are delivered with Var:ProductName support a variety of different file formats. A file type plug-in is a collection of components (classes) that support a range of common operations (e.g. detecting the file type, extracting translatable content, generating the target content in the respective native format, etc.). The file type plug-in components are used by the File Type Support Framework to process the data contained in a native file. The File Type Support Framework ships with plug-ins for common document formats such as Word, Excel, PowerPoint, XML, HTML, CSV, etc. The File Type Support Framework is designed to be extensible. This means that you can create additional plug-ins for file formats that are not supported by the standard installation of Var:ProductName. +## How the framework works -The File Type Support Framework operates on the concept of a processing chain. In order to process a file a chain of components needs to be set up that will read, process, and then write the translatable content. Some of these steps can be omitted if not required by the file format or your translation workflow. For example, you may not need to generate target file in the native document format if you just intend to read and a document. +When you open a native file, the File Type Support Framework selects the most suitable plug-in for the file format. It uses criteria such as the file name extension and metadata from the file header. + +Var:ProductName includes plug-ins for common formats, including Word, Excel, PowerPoint, XML, HTML, and CSV. The framework remains extensible, so you can add custom plug-ins for formats that the standard installation does not support. + +The framework also supports native, monolingual documents and bilingual formats, such as TTX and ITD. + +Each file type plug-in contains components that handle common tasks, such as: + +* detecting the file type +* extracting translatable content +* generating the target content in the native format + +The framework runs these components as a processing chain. Depending on the format and your workflow, you can omit steps that you do not need. For example, you might only need to extract content and skip target generation. + +## What you can do with the File Type Support SDK + +The File Type Support SDK includes sample projects that show how to address common localization requirements. + +* Process a file format that Var:ProductName does not support out of the box. +* Enforce a configurable minimum or maximum segment length across all document formats. +* Read XML formats that store length-limit information in tags and validate those limits in a custom file type. +* Keep HTML headings in the source language and verify that users do not translate them. + +These samples show how plug-ins can automate repetitive localization work, such as character counting and copying segments. diff --git a/apiconcepts/filetypesupport/overview_of_the_billingual_api.md b/apiconcepts/filetypesupport/overview_of_the_billingual_api.md index a8b0f8348d..aae8f90b76 100644 --- a/apiconcepts/filetypesupport/overview_of_the_billingual_api.md +++ b/apiconcepts/filetypesupport/overview_of_the_billingual_api.md @@ -1,23 +1,36 @@ -Overview of the Bilingual API -=== +# Overview of the Bilingual API -This section contains a quick overview of the Bilingual API. For detailed documentation on individual interfaces, properties, methods etc. see the reference documentation. +This section provides a quick overview of the Bilingual API. For detailed documentation on individual interfaces, properties, and methods, see the reference documentation. -Bilingual processor components implement the IBilingualContentProcessor interface, which the framework calls to let the component process content in a bilingual object model one paragraph unit at a time. +Bilingual processor components implement the IBilingualContentProcessor interface. The framework calls this interface to process content in a bilingual object model one paragraph unit at a time. ![BilingualContentProcessor](images/BilingualContentProcessor.png) -The content is delivered to the components through calls to [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_). The [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) method is invoked before any content is passed through the component, and it communicates the document properties which are common for all files in the document. For each native file in the bilingual document the framework calls [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) before the content of the file is processed. When all content in a file has been processed the framework calls [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_FileComplete) and when all files in a document have been processed the framework calls Complete. +The framework delivers content to components through calls to [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_). -The file properties passed through the [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) call can be used to retrieve the persistant file conversion settings, where components can store and retrieve important settings related to the data being processed. +The [Initialize](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_Initialize_Sdl_FileTypeSupport_Framework_BilingualApi_IDocumentProperties_) method runs before the framework passes any content through the component. It communicates the document properties that are common to all files in the document. + +Before processing the content of each native file, the framework calls [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_). + +After all content in a file has been processed, the framework calls [FileComplete](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_FileComplete). + +When all files in a document have been processed, the framework calls Complete. + +You can use the file properties passed to [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_) to retrieve the persistent file conversion settings. Components can store and retrieve settings related to the data being processed. ![FileProperties](images/FileProperties.png) -The ```EventFiringBilingualProcessor``` is an implementation of the [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface that is convenient to use when you are only interested in processing one or two of these calls. That implementation simply fires events for each of the calls and you can hook up your event handler to the one you are interested in. (This is very handy especially when writing unit tests.) +The `EventFiringBilingualProcessor` implements the [IBilingualContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentProcessor.yml) interface and provides a convenient way to use it when you only need to process one or two of these calls. This implementation fires events for each call, and you can subscribe to the event handler for the call you need. This approach is especially useful when writing unit tests. ![EventFiringBilingualProcessor](images/EventFiringBilingualProcessor.png) -Paragraph units can be devided into two types: structure paragraph units and localizable paragraph units. Structure paragraph units contain only structural data (i.e. structure tags), they have no directly localizable content. Localizable paragraph units contain text and tags that are modified during translation. Both types of paragraph units are processed in the [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) call, the implementation must check the [IsStructure](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_IsStructure) property to determine which type each is. +Paragraph units divide into two types: structure paragraph units and localizable paragraph units. + +Structure paragraph units contain only structural data (for example, structure tags). They have no directly localizable content. + +Localizable paragraph units contain text and tags that change during translation. + +The [ProcessParagraphUnit](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.AbstractBilingualContentProcessor.yml#Sdl_FileTypeSupport_Framework_BilingualApi_AbstractBilingualContentProcessor_ProcessParagraphUnit_Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_) call processes both types. Your implementation must check the [IsStructure](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_IsStructure) property to determine which type each is. ![StructureParagraphUnit](images/StructureParagraphUnit.png) @@ -25,7 +38,7 @@ A localizable paragraph unit can have the following main properties: ![LocalizableParagraphUnit](images/LocalizableParagraphUnit.png) -The source and target language content in a paragraph is comprised of objects that implement [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) derived interfaces: +The source and target language content in a paragraph comprise objects that implement [IMarkupDataVisitor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IMarkupDataVisitor.yml) derived interfaces: ![Paragraph](images/Paragraph.png) @@ -33,22 +46,34 @@ Here is a diagram with some more details on the inline tags: ![InlineTags](images/InlineTags.png) -Tags and text inside a paragraph can be annotated with different types of markup, represented with [IAbstractMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarker.yml) as base interface: +Tags and text inside a paragraph support annotation with different types of markup, represented by [IAbstractMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarker.yml) as the base interface: ![Markers](images/Markers.png) -The most important type of markup is segments. A segment is uniquely identified *within the paragraph unit* through its segment ID. As segment in a localized paragraph unit always has a source/target language counterpart. The source and target language segments reference the same [ISegmentPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ISegmentPair.yml) object, and thus implicitly will always have the same segment ID. The corresponding source/target segment can be easily retrieved through the [GetSourceSegment](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_GetSourceSegment_Sdl_FileTypeSupport_Framework_NativeApi_SegmentId_) and [GetTargetSegment](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_GetTargetSegment_Sdl_FileTypeSupport_Framework_NativeApi_SegmentId_) methods, which take the segment ID as parameter and returns the corresponding object. +Segments are the most important type of markup. A segment is uniquely identified *within the paragraph unit* through its segment ID. -Navigation and iteration through the bilingual content in a paragraph or other markup data container can be achieved in a number of different ways. Perhaps the most intuitive is to use the ```Parent```, ```IndexInParent``` and ```Items``` properties to directly access related nodes, or by iterating over all items in an [IAbstractMarkupDataContainer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarkupDataContainer.yml) either directly or through the [AllSubItems](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarkupDataContainer.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IAbstractMarkupDataContainer_AllSubItems) property of the container, or by calling the [ForEachSubItem](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarkupDataContainer.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IAbstractMarkupDataContainer_ForEachSubItem_System_Action_Sdl_FileTypeSupport_Framework_BilingualApi_IAbstractMarkupData__) method passing in an action object. +A segment in a localized paragraph unit always has a source/target language counterpart. The source and target language segments reference the same [ISegmentPair](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ISegmentPair.yml) object, and thus implicitly share the same segment ID. + +You can easily retrieve the corresponding source or target segment using the [GetSourceSegment](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_GetSourceSegment_Sdl_FileTypeSupport_Framework_NativeApi_SegmentId_) and [GetTargetSegment](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IParagraphUnit.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IParagraphUnit_GetTargetSegment_Sdl_FileTypeSupport_Framework_NativeApi_SegmentId_) methods. These methods take the segment ID as a parameter and return the corresponding object. + +You can navigate and iterate through the bilingual content in a paragraph or other markup data container in several ways. + +The most intuitive approach uses the `Parent`, `IndexInParent`, and `Items` properties to directly access related nodes. + +Alternatively, iterate over all items in an [IAbstractMarkupDataContainer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarkupDataContainer.yml) directly or through the [AllSubItems](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarkupDataContainer.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IAbstractMarkupDataContainer_AllSubItems) property. + +You can also call the [ForEachSubItem](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IAbstractMarkupDataContainer.yml#Sdl_FileTypeSupport_Framework_BilingualApi_IAbstractMarkupDataContainer_ForEachSubItem_System_Action_Sdl_FileTypeSupport_Framework_BilingualApi_IAbstractMarkupData__) method and pass in an action object. The [Location](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.Location.yml) class provides another flexible way of iterating through and working with the localizable content in a paragraph: ![Locations](images/Locations.png) -Localizable content can also be processed through a visitor pattern. This is often useful when dealing with collections of objects (e.g. in markup data containers), as the use of a visitor avoids having to construct awkward and difficult to maintain ```switch```/```if``` statements to test for different object types. Simply call ```AcceptVisitor``` on the object, and the object will call back to its corresponding method on the visitor. For more information about the Visitor pattern, see *Design Patters* by the “Gang of Four” (Gamma, Helm, Johnson, Vlissides), a book that should be on every developer's desk. +You can also process localizable content through the visitor pattern. This approach is especially useful when dealing with collections of objects (for example, in markup data containers). Using a visitor pattern avoids constructing awkward and difficult to maintain ```switch```/```if``` statements to test for different object types. + +Call ```AcceptVisitor``` on the object, and the object calls back to the corresponding method on the visitor. For more information about the visitor pattern, see *Design Patterns* by the Gang of Four (Gamma, Helm, Johnson, Vlissides). ![VisitorPattern](images/VisitorPattern.png) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. \ No newline at end of file diff --git a/apiconcepts/filetypesupport/overview_of_the_native_api.md b/apiconcepts/filetypesupport/overview_of_the_native_api.md index 12d191f766..553358a4e1 100644 --- a/apiconcepts/filetypesupport/overview_of_the_native_api.md +++ b/apiconcepts/filetypesupport/overview_of_the_native_api.md @@ -1,79 +1,97 @@ -Overview of the Native API -=== +# Overview of the Native API -This section contains a quick overview of the Native API. +This section provides a high-level overview of the Native API. -The Native API contains the functionality needed to build filters and filter components for processing monolingual content in a native doucment format (e.g. Microsoft Word). Most file filters and file processing components can be built using only this API of the Var:ProductName. The only exceptions where the native API is not sufficient are those in which you need to explicitly process content available in bilingual form, e.g. if working with bilingual file formats such as TTX or ITD. +The Native API provides the functionality that you need to build filters and filter components for monolingual content in a native document format, such as Microsoft Word. You can build most file filters and file-processing components in Var:ProductName by using only this API. You only need a different approach when you must explicitly process bilingual content, such as TTX or ITD files. -The core of the native API is the [IAbstractNativeContentHandler](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml) interface. All the content processing (output, input or both) happens through this interface. (This interface is somewhat similar to the ```IEvents``` interface of File Type Support Framework 1.) The following diagram provides and overview of the native content handler interface and components that are directly related to it: +## Native content handler + +The core of the Native API is the [IAbstractNativeContentHandler](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml) interface. All content processing, whether input, output, or both, passes through this interface. This interface is similar to the `IEvents` interface in File Type Support Framework 1. The following diagram shows the native content handler interface and the components that relate to it: ![NativeExtractor](images/NativeExtractor.png) -From the above diagram you can see that parsers use this interface to generate their output, while writers use the interface as input (???) (the writer implements the interface and receives calls on it from other filter components). The native content processor uses the content handler interface both as input and output. It receives calls on its implementation of the interface, and as a result of these calls, sends calls to another content handler. +Parsers use this interface to generate output. Writers use the interface as input: the writer implements the interface and receives calls from other filter components. Native content processors use the interface as both input and output. They receive calls through their implementation and then forward corresponding calls to another content handler. + +## Text and tags Localizable content that is processed in the framework is divided into **text** and **tags**. All localizable text processed by the framework is passed through the [Text](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_Text_Sdl_FileTypeSupport_Framework_NativeApi_ITextProperties_) method in this interface. Tags are passed as calls to either of the following methods: -* [StructureTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_StructureTag_Sdl_FileTypeSupport_Framework_NativeApi_IStructureTagProperties_): tags that represent structural information in the file. This is the equivalent of the external tags in File Type Support Framework 1. -* [InlinePlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlinePlaceholderTag_Sdl_FileTypeSupport_Framework_NativeApi_IPlaceholderTagProperties_): standalone tags that may appear inside localizable text and that may need to be placed and/or duplicated during translation, This is the equivalent of standalone inline tags in File Type Support Framework 1. -* [InlineStartTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlineStartTag_Sdl_FileTypeSupport_Framework_NativeApi_IStartTagProperties_) and InlineEndTag: paired tags, which can appear inside localizable text and which usually need to be placed and/or duplicated (as a pair) during translation. The framework requires these calls to be nested according to standard XML rules, i.e.: - * Each call to ```InlineStartTag()``` must be matched by a call to InlineEndTag() at a later point during content processing. Note that text content will usually occur within a start and end tag, which may include other, similarly nested tag pairs. - * A call to ```InlineEndTag()``` **must never** occur before a (corresponding) call to InlineStartTag(). - * A call to ```InlineEndTag()``` will always be interpreted by the framework as matching the last “unmatched” call to ```InlineStartTag()```, i.e. the last of the previous calls to ```InlineStartTag()``` for which no other call to ```InlineEndTag()``` has been matched. +* [StructureTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_StructureTag_Sdl_FileTypeSupport_Framework_NativeApi_IStructureTagProperties_): represents structural information in the file. This is the equivalent of external tags in File Type Support Framework 1. +* [InlinePlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlinePlaceholderTag_Sdl_FileTypeSupport_Framework_NativeApi_IPlaceholderTagProperties_): represents standalone tags that can appear inside localizable text and that translators may need to place or duplicate. This is the equivalent of standalone inline tags in File Type Support Framework 1. +* [InlineStartTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlineStartTag_Sdl_FileTypeSupport_Framework_NativeApi_IStartTagProperties_) and `InlineEndTag`: represent paired tags that can appear inside localizable text and that translators usually need to place or duplicate as a pair. The framework requires these calls to follow standard XML nesting rules: + * Each call to `InlineStartTag()` must be matched by a later call to `InlineEndTag()`. Text content usually appears within a start and end tag and can include other nested tag pairs. + * A call to `InlineEndTag()` must never occur before the corresponding call to `InlineStartTag()`. + * A call to `InlineEndTag()` always matches the last unmatched call to `InlineStartTag()`. -If the nesting rules are not followed to the letter, the framework will throw an exception. Note that these new rules did not apply in File Type Support Framework 1. However, start and end tags in File Type Support Framework 1 were always effectively nested this way by filters anyway. +If you do not follow these nesting rules, the framework throws an exception. File Type Support Framework 1 did not enforce these rules explicitly, but filters still nested start and end tags in the same way in practice. Each of the methods in the content handler interface take property objects, which describe the actual data passed through the call. The tag properties have the following relations and content: ![TagProperties](images/TagProperties.png) -All the properties objects implement the ```ICloneable``` interface. They are cloned when inserted in bilingual content models and when inserted in a buffer. This ensures that the properties do not get implicitly changed. +All property objects implement the `ICloneable` interface. The framework clones them when it inserts them into bilingual content models or buffers. This behavior prevents implicit changes to the properties. + +## Context information Information on the structure of the file and other relevant context information that may be relevant for the translation can also be communicated through the framework. For this purpose, the method [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_) is used. -The context properties passed in the ```ChangeContext()``` method contains both the document structure information and the context information relevant for localization purposes: +The context properties that you pass to `ChangeContext()` contain both document structure information and localization context information: ![Context](images/Context.png) -The localization context information is a prioritized list of individual contexts. The context that is most significant for the translation should be first in the list. Each context is structured as follows: +Localization context information is a prioritized list of individual contexts. Put the context that matters most for translation first in the list. Each context has the following structure: ![ContextInfo](images/ContextInfo.png) -If a context is intended to be used by localization tools to e.g. to impact recycling or disambiguate multiple matches in a translation memory its [Purpose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextInfo_Purpose) property should be set to [Match](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields) . If the context is meant only as additional information to the translator its context purpose should be [Information](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields). The [Location](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields) purpose is used by the framework in the bilingual ```content``` model to reference the location of the tag for paragraph units that hold any localizable tag content. +If localization tools should use a context to affect recycling or disambiguate multiple translation memory matches, set its [Purpose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextInfo_Purpose) property to [Match](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields). If the context only provides additional information to the translator, set its purpose to [Information](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields). The [Location](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ContextPurpose.yml#fields) purpose is used by the framework in the bilingual `content` model to reference the location of the tag for paragraph units that contain localizable tag content. + +The [StandardContextTypes](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.StandardContextTypes.yml) list defines well-known context types. Use these types whenever possible to ensure the best tool support and cross-file-type compatibility. If none of the well-known types fit, define a custom context. -The [StandardContextTypes](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Utilities.NativeApi.StandardContextTypes.yml) is a list of well-known context types. These should be used by filters whenever appropriate in order to ensure the best possible tool support and cross-file type compatibility. If no context in the well-known list is appropriate, a custom context can be specified. +You can store additional context information in the [IMetaDataContainer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml) key/value collection. This metadata lets filters and filter components exchange document metadata. The default bilingual file format also serializes this metadata with the context. -Additional information on a context can be stored in the [IMetaDataContainer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml) key/value pair collection. The purpose of this information is to enable filters and filter components to use contexts for communication of document meta-data. This information is also serialized together with the context in the default bilingual file format. +A context can also include semi-WYSIWYG formatting. If several contexts include formatting information, use the combined formatting as the base formatting for all paragraph units to which the contexts apply. You can retrieve the combined formatting from the [EffectiveDefaultFormatting](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_EffectiveDefaultFormatting) property. -A context may also have semi-WYSIWYG formatting associated with it. If several contexts are associated with formatting information, the combined formatting should be used as base formatting for all paragraph units the contexts apply to. The combined formatting can be retrieved from the [EffectiveDefaultFormatting](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_EffectiveDefaultFormatting) property. +Other context properties control how the context is displayed to the user. Filter components should only set these properties for contexts that are not part of `StandardContextTypes`. -Other properties of the context are used to specify how the context may be displayed to the user. Filter components should only set these for contexts that are not part of the ```StandardContextTypes```. +## Document structure The document structure context can be used to generate an overview of the document content. It contains the following information: ![StructureInfo](images/StructureInfo.png) -All property objects passed through the methods in the ```IAbstractNativeContentHandler``` are created through a property factory that is provided by the framework. The [IPropertiesFactory](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml) interface looks like this: +All property objects that pass through the `IAbstractNativeContentHandler` methods are created by a property factory that the framework provides. The [IPropertiesFactory](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml) interface looks like this: ![PropertiesFactory](images/PropertiesFactory.png) -Filter components may implement [INativeFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileTypeComponent.yml) , as shown in the following diagram: +## Native file type components + +Filter components can implement [INativeFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileTypeComponent.yml), as shown in the following diagram: ![NativeFileTypeComponent](images/NativeFileTypeComponent.png) -The framework uses this interface to provide facilities such as the properties factory and the message reporter to the filter components. When creating your own components you may choose to (but are not required to) derive them from the [AbstractNativeFileTypeComponent)](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileTypeComponent.yml) or one of its derived classes: [AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml), [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml), [AbstractNativeGenerationContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeGenerationContentProcessor.yml), [AbstractNativeExtractionGenerationContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeExtractionContentProcessor.yml), which all 1implement this interface for you. You can then access the properties factory and the message reporter directly through their property names withouth any additional implementation work. +The framework uses this interface to provide services such as the properties factory and the message reporter to filter components. When you create your own components, you can derive them from [AbstractNativeFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileTypeComponent.yml) or one of its derived classes, although this is optional: + +* [AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml) +* [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml) +* [AbstractNativeGenerationContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeGenerationContentProcessor.yml) +* [AbstractNativeExtractionGenerationContentProcessor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeExtractionContentProcessor.yml) -Components may also implement the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface, which the framework uses to communicate to the components when parsing starts and ends, and allows components to store and retrieve settings that will be persisted as part of the bilingual format: +These classes implement the interface for you. You can then access the properties factory and the message reporter directly through their properties without adding extra implementation code. + +Components can also implement the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface. The framework uses this interface to notify components when parsing starts and ends. It also lets components store and retrieve settings that persist as part of the bilingual format: ![PersistentFileConversionProperties](images/PersistentFileConversionProperties.png) -Native filter components can be grouped together to perform reading and writing operations through the Extractor and Generator converters: +## Extractor, generator, and buffering + +You can group native filter components together to perform reading and writing operations through the Extractor and Generator converters: ![ExtractorAndGenerator](images/ExtractorAndGenerator.png) -The forward converter manages a file parser and an associated set of content processors that work together to perform conversion from the native format. The backward converter in a similar way manages a collection of content processors and a writer that can be operated as one unit. +The forward converter manages a file parser and an associated set of content processors that work together to convert content from the native format. The backward converter similarly manages a collection of content processors and a writer that operate as a single unit. -Content processors typically apply specialized tasks to the content stream. Examples include detecting localizable content inside tags, marking up embedded HTML content in strings, conversion of XML/SGML/HTML entities, etc. When developing content processors it is sometimes necessary to examine content later in the stream in order to determine how to process preceding content. This means that the component must buffer streaming content until it has enough information to process it. The framework contains a buffer component that can be used for this purpose: +Content processors typically apply specialized tasks to the content stream. Examples include detecting localizable content inside tags, marking up embedded HTML content in strings, and converting XML, SGML, or HTML entities. When you develop content processors, you sometimes need to inspect later content in the stream before you can process earlier content. In that case, the component must buffer the stream until it has enough information to continue. The framework provides a buffer component for this purpose: ![Buffer](images/Buffer.png) diff --git a/apiconcepts/filetypesupport/previewing_files.md b/apiconcepts/filetypesupport/previewing_files.md index 8df73a1edd..54300898f3 100644 --- a/apiconcepts/filetypesupport/previewing_files.md +++ b/apiconcepts/filetypesupport/previewing_files.md @@ -1,29 +1,29 @@ -Previewing files -==== -Var:ProductName presents the source and target text in an 'abstracted' view, which gives users a general idea of the layout only through context information (see Using context information). However, for translators and editors it is often useful to view the 'real' document layout. This is why a file type plug-in should ideally be able to generate the source or target document (or both) in the native format, thus giving the users an idea of the actual document layout. +# Previewing files -Var:ProductName allows you to generate a document preview in an external application for virtually any supported document format. For example: When you process an Adobe FrameMaker file in Var:ProductName and you choose to view the file in the corresponding external application, Adobe FrameMaker will be launched - provided, of course, that the FrameMaker application is installed on your machine. If this is not the case, then no preview in the external application is possible and a corresponding error message will be thrown. +Var:ProductName presents source and target text in an abstracted view that relies on context information. See [Using context information](using_context_information.md). However, translators and reviewers often need to inspect the actual document layout. For that reason, a file type plug-in should ideally generate the source document, the target document, or both in the native format. -In addition to generating a preview in a separate application you can also embed the preview in Var:ProductName itself. In this case the document preview will be generated in an embedded window. Currently, Var:ProductName supports this type of preview for the following formats: Microsoft Word, Microsoft PowerPoint, HTML, and XML. +## External previews -The internal preview can be static or dynamic. Static means that the preview window shows the preview document, but it does not interact with the side-by-side editor. On the other hand, a dynamic preview interacts with the segments in the side-by-side editor. When you click, for example, a segment in the preview window, the corresponding segment in the editor will be highlighted (and vice versa). Internal preview windows usually rely on a display component, which does not require the actual application. For example, for Microsoft Word documents Var:ProductName leverages a Word viewer component, which allows you to preview Word documents even if Microsoft Word is not installed on your machine. The HTML preview leverages a Web browser component. +Var:ProductName can generate a document preview in an external application for almost any supported document format. For example, when users process an Adobe FrameMaker file in Var:ProductName and choose the external preview, Var:ProductName launches Adobe FrameMaker if it is installed on the machine. If the application is unavailable, Var:ProductName cannot open the external preview and displays an error message. -A file type plug-in can be designed to generate previews for the source document, the target document or both (side-by-side.) +## Internal previews -Example of an internal preview in for a Microsoft Word document in Var:ProductName. The preview can be generated for the source or target language or for both at the same time (side-by-side). The file type plug-in for Microsoft Word files, however, does not generate a side-by-side preview, as this would take too much screen space, and this might also be a performance issue. +Var:ProductName can also host the preview inside the application. In that case, the preview appears in an embedded window. Var:ProductName currently supports embedded previews for Microsoft Word, Microsoft PowerPoint, HTML, and XML. - +Internal previews can be static or dynamic. A static preview shows the document, but it does not interact with the side-by-side editor. A dynamic preview stays synchronized with the editor. When users select a segment in the preview, Var:ProductName highlights the corresponding segment in the editor, and vice versa. Internal previews usually rely on a display component instead of the native application. For example, Var:ProductName uses a Word viewer component to preview Word documents even when Microsoft Word is not installed. The HTML preview uses a web browser component. -See Also ----------- -[Implementing an External File Preview](implementing_an_external_file_preview.md) +A file type plug-in can generate previews for the source document, the target document, or both side by side. -[Implementing the Preview Writer](implementing_the_preview_writer.md) +## Example -[Enhancing the Preview File Writer](enhancing_the_preview_file_writer.md) +This example shows the internal preview for a Microsoft Word document in Var:ProductName. The preview can show the source language, the target language, or both at the same time. The Microsoft Word file type plug-in does not provide a side-by-side preview because that layout uses too much screen space and can affect performance. -[Adding a Preview UI Control](adding_a_preview_ui_control.md) +Internal preview for a Microsoft Word document in Var:ProductName -[Adding a Preview Controller](adding_a_preview_controller.md) - -[Appendix: Real-time Preview for XML Files](appendix_real_time_preview_for_xml_files.md) +## See also +- [Implementing an External File Preview](implementing_an_external_file_preview.md) +- [Implementing the Preview Writer](implementing_the_preview_writer.md) +- [Enhancing the Preview File Writer](enhancing_the_preview_file_writer.md) +- [Adding a Preview UI Control](adding_a_preview_ui_control.md) +- [Adding a Preview Controller](adding_a_preview_controller.md) +- [Appendix: Real-time Preview for XML Files](appendix_real_time_preview_for_xml_files.md) diff --git a/apiconcepts/filetypesupport/processing_inline_formatting.md b/apiconcepts/filetypesupport/processing_inline_formatting.md index 910cb43cb2..aeb35d1ab7 100644 --- a/apiconcepts/filetypesupport/processing_inline_formatting.md +++ b/apiconcepts/filetypesupport/processing_inline_formatting.md @@ -1,18 +1,20 @@ -Processing Inline Formatting --- +# Processing Inline Formatting In this chapter you will learn how to enhance your file type plug-in to properly mark up inline tags and apply character formatting. -Add New Members to the Parser Class --- +## Add New Members to the Parser Class -For your parser class to be able to identify inline tags embedded within translatable content and to apply character display formatting, you need to make the following additions: +For your parser class to identify inline tags embedded within translatable content and apply character display formatting, add the following items: -Since we will use regular expressions to identify tags within translatable strings, you need to add the regular expressions namespace to your class, i.e. ```System.Text.RegularExpressions``` +First, add the regular expressions namespace to your class because you will use regular expressions to identify tags within translatable strings: -Second, add the ```Sdl.FileTypeSupport.Framework.Formatting``` namespace. This namespace is required to access the functionality used to apply display character formatting in the editor of Var:ProductName. +``` +System.Text.RegularExpressions +``` + +Second, add the `Sdl.FileTypeSupport.Framework.Formatting` namespace. This namespace provides the functionality to apply display character formatting in the editor of Var:ProductName. -To keep this project simple, let us proceed on the assumption that a text file can only contain the < b> tag for applying bold character formatting. To reflect this in your code, add a new formatting member to the global settings of your class: +To keep this project simple, assume the text file contains only the `` tag for applying bold character formatting. Add a new formatting member to the global settings of your class: # [C#](#tab/tabid-1) ```cs @@ -23,10 +25,9 @@ FormattingGroup _fBold; ``` *** -Add the Functionality Required for Processing Formatting --- +## Add the Functionality Required for Processing Formatting -Change the ```ProcessLine()``` helper as shown below, so that a new ```ProcessFormatting()``` function is called through ```WriteText()```. (We will add this new helper function for processing formatting in the next step.) +Modify the `ProcessLine()` helper function to call a new `ProcessFormatting()` function through `WriteText()`. (You will add this helper function in the next step.) # [C#](#tab/tabid-2) ```cs @@ -49,7 +50,7 @@ private void ProcessLine(string sLine) ``` *** -Now add the function that identifies inline tag content (if available) within a translatable line: +Now add the function that identifies inline tag content within a translatable line: # [C#](#tab/tabid-3) ```cs @@ -87,11 +88,11 @@ Next, add the function that outputs the inline < b> tags. Note that these inline > >Start tags and end tags must be well-formed in the XML sense, i.e. all start tags must match an end tag with the same nesting of paired tags. If not, the File Type Support Framework will throw a fatal exception. When paired tags are processed by the File Type Support Framework and the framework-based editor, this well-formedness is guaranteed to be preserved. This can simplify other tag processing modules such as the native file writer (see [Implementing the File Writer](implementing_the_file_writer.md)). -**Outputting the start tag of a tag pair**: The properties factory provides a [CreateStartTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateStartTagProperties_System_String_) method that creates properties for a start tag that may appear inside localizable content and that has a corresponding end tag. When creating the tag property the tag content is passed to the Create() method as a parameter. The start tag property can then be output to the API using ```Output.InlineStartTag()```. +**Outputting the start tag of a tag pair**: The properties factory provides a [CreateStartTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateStartTagProperties_System_String_) method that creates properties for a start tag inside localizable content. The start tag has a corresponding end tag. Pass the tag content to the `Create()` method as a parameter. Output the start tag property to the API using `Output.InlineStartTag()`. -**Outputting the end tag of a tag pair**: The properties factory has a [CreateEndTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateEndTagProperties_System_String_) method that creates properties for an end tag, which matches a previously emitted start tag. When creating the tag property the tag content is passed to the ```Create()``` method as a parameter. The end tag property can then be output to the API through the method ```OutputInlineEndTag()```. +**Outputting the end tag of a tag pair**: The properties factory provides a [CreateEndTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPropertiesFactory.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPropertiesFactory_CreateEndTagProperties_System_String_) method that creates properties for an end tag matching a previously emitted start tag. Pass the tag content to the `Create()` method as a parameter. Output the end tag property to the API using `OutputInlineEndTag()`. -This function also creates a formatting object to apply bold display formatting in the editor for the translator's convenience. We use the [CanHide](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractInlineTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractInlineTagProperties_CanHide) property to hide the inline tags by default. This means that the translator will only see the formatting, not the actual tags, which is usually more convenient for the translation process. +This function also creates a formatting object to apply bold display formatting in the editor for the translator's convenience. Use the [CanHide](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractInlineTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractInlineTagProperties_CanHide) property to hide the inline tags by default. Translators see only the formatting, not the actual tags, which is usually more convenient for the translation process. # [C#](#tab/tabid-4) ```cs @@ -124,24 +125,21 @@ private void WriteInlineTag(string tagContent, bool isStart) ``` *** -Through the (optional) [DisplayText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractBasicTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractBasicTagProperties_DisplayText) property you can define the tag text that users see when they decide to display inline tags in the partial tag text mode. The [TagContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractBasicTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractBasicTagProperties_TagContent) property determines the tag text that users see when they activate the full tag text view. +Use the [DisplayText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractBasicTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractBasicTagProperties_DisplayText) property to define the tag text that users see when they enable partial tag text mode. The [TagContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractBasicTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractBasicTagProperties_TagContent) property determines the tag text that users see when they enable full tag text view. -Below you see what the text looks like with proper display character formatting: +Below, the text displays with proper character formatting: ![OnlyFormatting](images/OnlyFormatting.jpg) - -This is what the editor view will look like when the user decides to display inline tags (partial tag text): +This is the editor view when the user enables inline tags (partial tag text): ![PartialTagText](images/PartialTagText.jpg) - -This is what the editor view will look like when the user decides to display inline tags (full tag text): +This is the editor view when the user enables inline tags (full tag text): ![FullTagText](images/FullTagText.jpg) -Putting it All Together --- +## Putting It All Together The enhanced file parser class should now look as shown below: @@ -159,14 +157,11 @@ namespace Sdk.Snippets.Native { public class SimpleTextParser : AbstractNativeFileParser, INativeContentCycleAware { - #region "global settings" IPersistentFileConversionProperties _fileConversionProperties; StreamReader _reader = null; FormattingGroup _fBold; - #endregion - #region "INativeContentCycleAware members" // through the properties object you can retrieve important information // on the native input file such as the original file name and path public void SetFileProperties(IFileProperties properties) @@ -184,11 +179,7 @@ namespace Sdk.Snippets.Native { } - #endregion - - #region "members of AbstractNativeFileParser" - #region "before parsing" protected override void BeforeParsing() { // set progress reporter to the beginning @@ -197,9 +188,7 @@ namespace Sdk.Snippets.Native // open the native input file for reading _reader = new StreamReader(_fileConversionProperties.OriginalFilePath); } - #endregion - #region "during parsing" protected override bool DuringParsing() { // iterate through all lines in the input file @@ -209,9 +198,7 @@ namespace Sdk.Snippets.Native } return false; } - #endregion - #region "after parsing" protected override void AfterParsing() { //close original file @@ -221,11 +208,7 @@ namespace Sdk.Snippets.Native //set progres report to 100% OnProgress(100); } - #endregion - #endregion - - #region "process line" // determines whether a given line is // translatable or not // if not, a structure tag is output @@ -242,18 +225,14 @@ namespace Sdk.Snippets.Native WriteText(ProcessFormatting(sLine)); } } - #endregion - #region "text" // output translatable text private void WriteText(string TextContent) { ITextProperties textProperties = PropertiesFactory.CreateTextProperties(TextContent); Output.Text(textProperties); } - #endregion - #region "structure" // output non-translatable text as structure tag private void WriteStructureTag(string TagContent) { @@ -261,9 +240,7 @@ namespace Sdk.Snippets.Native structureTagProperties.DisplayText = TagContent; Output.StructureTag(structureTagProperties); } - #endregion - #region "context" // output context information, not required, but useful // information for the translator private void WriteContext(string ContextContent) @@ -277,9 +254,7 @@ namespace Sdk.Snippets.Native contextProperties.Contexts.Add(contextInfo); Output.ChangeContext(contextProperties); } - #endregion - #region "process formatting" // this function uses regular expressions to identify // what is 'normal' translatable content and which strings // need to be marked up as inline tags, e.g. @@ -304,9 +279,7 @@ namespace Sdk.Snippets.Native } return sLine.Substring(LastPosition, sLine.Length - LastPosition); } - #endregion - #region "write inline tag" // this function outputs an opening or a closing tag // and applies bold character formatting to the strings // that the tags enclose @@ -333,24 +306,17 @@ namespace Sdk.Snippets.Native Output.InlineEndTag(endTag); } } - #endregion } } ``` *** -See Also --- - - - -[Implementing the File Parser](implementing_the_file_parser.md) - -[Processing Placeholder Tags](processing_placeholder_tags.md) - -[Handling Tags During Segmentation](handling_tags_during_segmentation.md) +## See Also -[Tag display modes](tag_display_modes.md) +- [Implementing the File Parser](implementing_the_file_parser.md) +- [Processing Placeholder Tags](processing_placeholder_tags.md) +- [Handling Tags During Segmentation](handling_tags_during_segmentation.md) +- [Tag display modes](tag_display_modes.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/processing_inline_tags.md b/apiconcepts/filetypesupport/processing_inline_tags.md index 60944dceeb..844e43d3cf 100644 --- a/apiconcepts/filetypesupport/processing_inline_tags.md +++ b/apiconcepts/filetypesupport/processing_inline_tags.md @@ -1,10 +1,8 @@ -Processing Inline Tags -=== +# Processing Inline Tags In this chapter you will learn how to parse inline tags and how to display character formatting in the side-by-side editing environment of Var:ProductName. -Enhance the Helper Function for Creating Segments --- +## Enhance the Helper Function for Creating Segments The segments in our bilingual sample format can contain the following inline tags: *< b>*, *< i>*, and *< u>*. To keep this example simple let us proceed on the assumption that only these three inline tag types can occur in a seg element. @@ -14,9 +12,8 @@ A segment with inline tags may look as follows: ```html Open the dialog box. ``` -*** -You need to enhance the ```CreateSegment()``` helper function to loop through the segment node and create a text object or a tag depending on whether a sub-node found in the segment is of the type **text** or of the type **element**. If a text node is found, you call another helper function (```CreateText()```) that adds the text to the segment or ```CreateTagPair()``` that creates a tag pair: +You need to enhance the `CreateSegment()` helper function to loop through the segment node and create a text object or a tag depending on whether a sub-node is of type **text** or **element**. When you find a text node, call another helper function (`CreateText()`) that adds the text to the segment, or call `CreateTagPair()` to create a tag pair: # [C#](#tab/tabid-2) ```cs @@ -40,12 +37,10 @@ private ISegment CreateSegment(XmlNode segNode, ISegmentPairProperties pair) return segment; } ``` -*** -Add the Helper Function for Generating Text --- +## Add the Helper Function for Generating Text -For convenience reasons, 'outsource' the generation of text items to a separate helper function, which looks as shown below: +Create a separate helper function to generate text items for convenience: # [C#](#tab/tabid-3) ```cs @@ -57,14 +52,14 @@ private IText CreateText(string segText) return textContent; } ``` -*** -Add the Helper Function for Generating Tag Pairs --- +## Add the Helper Function for Generating Tag Pairs -Now add the function for generating tag pairs. This function works as follows: The properties factory is leveraged to create the start and the end tag properties. The display text of the tags is the tag text that users see when the (default) partial tag text mode of Var:ProductName is activated. Then we use the item factory to generate the actual tag pair object based on the start and end tag properties. Note that each opening tag requires a closing tag, i.e. the bilingual document needs to be well-formed in an XML sense. If that is not the case, the framework will raise a critical error. +Add the function for generating tag pairs. This function works as follows: -Do not forget to extract also the text that is enclosed in the tag pair. To this end we call the ```CreateText()``` helper function, which generates the text between the opening and the closing tag, which is then appended to the tag pair. +The properties factory creates the start and end tag properties. The display text of the tags is what users see when they activate the (default) partial tag text mode of Var:ProductName. Then the item factory generates the actual tag pair object based on the start and end tag properties. Each opening tag requires a closing tag, so the bilingual document must be well-formed in an XML sense. If not, the framework raises a critical error. + +Extract the text enclosed in the tag pair by calling the `CreateText()` helper function. This generates the text between the opening and closing tag, which you then append to the tag pair. # [C#](#tab/tabid-4) ```cs @@ -72,7 +67,6 @@ private ITagPair CreateTagPair(XmlNode item) { // create the start and the end tag IStartTagProperties startTag = PropertiesFactory.CreateStartTagProperties(item.Name); - #region "formatting" // apply character formatting to the start tag IFormattingGroup formattingGroup = PropertiesFactory.FormattingItemFactory.CreateFormatting(); startTag.Formatting = new FormattingGroup(); @@ -91,7 +85,6 @@ private ITagPair CreateTagPair(XmlNode item) break; } startTag.Formatting = formattingGroup; - #endregion startTag.DisplayText=item.Name; startTag.CanHide = true; @@ -114,12 +107,9 @@ After you have enhanced your file type plug-in as described above, the BIL sampl ![BilWithTags](images/BilWithTags.jpg) -See Also --- - - +## See Also -[Applying Character Formatting](applying_character_formatting.md) +- [Applying Character Formatting](applying_character_formatting.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/processing_native_formats_introduction.md b/apiconcepts/filetypesupport/processing_native_formats_introduction.md index 0f6e5390cb..ae87a8cca6 100644 --- a/apiconcepts/filetypesupport/processing_native_formats_introduction.md +++ b/apiconcepts/filetypesupport/processing_native_formats_introduction.md @@ -1,34 +1,34 @@ -Introduction -=== +# Introduction -This guide takes you step by step through the creation of a custom file type plug-in for processing simple text files. +This guide walks you through the creation of a custom file type plug-in that processes simple text files. -Implement a File Type Plug-in for Processing Simple Text Files --- +## Implement a file type plug-in for simple text files -Imagine that you need to create a file type plug-in for processing simple (monolingual) text files that look as shown below: +Suppose you need to create a file type plug-in for simple monolingual text files such as the following: -# [Text](#tab/tabid-1) -``` +```text [Version=0] [Element=text1] Automatically re-open previously edited documents. [Element=text2] Prompt me to re-open previously edited documents. Opens a dialog box on start-up. [Element=text3] -Do not automatically re-open previously edited couments. This is the default option. +Do not automatically re-open previously edited documents. This is the default option. [Element=text4] Prd-Code NCC1504 ``` -*** + +## Localization requirements This text format has the following localization requirements: -* The lines that are enclosed in brackets (i.e. []) must be protected from editing and thus from translation. -* The lines that are not enclosed in brackets require localization. -* Translatable text may be enclosed in common HTML tags (e.g. < b >). The file type plug-in needs to recognize tag text as inline elements and apply bold display formatting in the editor of Var:ProductName. -* Let us assume that the file name extension for this file type is **.text*. -* Certain strings (e.g. *Prd-Code NCC1504*) have to be locked, so that they cannot be changed by the translator. -To be sure, you could also process this format using the standard regular expressions text file type plug-in, which is included in Var:ProductName out-of-the-box. However, for this exercise we would like to show to you how to implement a 'no-frills' file type plug-in for a highly simplified text format. This allows you to develop a file type plug-in with a minimum amount of native file processing logic (and thus source code). + +- Protect lines enclosed in brackets (`[]`) from editing and translation. +- Localize lines that are not enclosed in brackets. +- Recognize common HTML tags such as `` as inline elements and apply bold formatting in the Var:ProductName editor. +- Assume that this file type uses the `.text` file name extension. +- Lock specific strings, such as `Prd-Code NCC1504`, so translators cannot change them. + +You could also process this format with the standard regular expressions text file type plug-in that Var:ProductName includes out of the box. This exercise instead shows how to implement a simple file type plug-in for a highly simplified text format. That approach lets you focus on the minimum native file processing logic required. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/processing_placeholder_tags.md b/apiconcepts/filetypesupport/processing_placeholder_tags.md index cf3d2f4dac..81928da67e 100644 --- a/apiconcepts/filetypesupport/processing_placeholder_tags.md +++ b/apiconcepts/filetypesupport/processing_placeholder_tags.md @@ -1,12 +1,10 @@ -Processing Placeholder Tags -=== +# Processing Placeholder Tags In one of the previous chapters you learned how to process tag pairs (e.g. ) during file parsing (see [Processing Inline Formatting](processing_inline_formatting.md)). In this chapter you will learn how to process standalone placeholder tags, such as < img src="button.jpg" /> -Enhance your Parser to Process Standalone Placeholder Tags --- +## Enhance your Parser to Process Standalone Placeholder Tags -Let us assume that your sample text files sometimes contain tags for referencing images, e.g.: +Assume your sample text files sometimes contain tags for referencing images, for example: # [HTML](#tab/tabid-1) ```html @@ -23,9 +21,9 @@ the dialog box. ``` *** -These tags are closed within themselves and occur as placeholders within the text. To keep this example as simple as possible let us proceed on the assumption that the **IMG** tag is the only placeholder tag that we can expect to find in any given document. +These tags close within themselves and occur as placeholders within the text. To keep this example simple, assume the **IMG** tag is the only placeholder tag that your document will contain. -Start by making a small change to the ```ProcessFormatting()``` helper function: if the regular expression pattern found a match that starts on "**[!NOTE] > diff --git a/apiconcepts/filetypesupport/putting_it_all_together.md b/apiconcepts/filetypesupport/putting_it_all_together.md index e37911ff39..4469f0b832 100644 --- a/apiconcepts/filetypesupport/putting_it_all_together.md +++ b/apiconcepts/filetypesupport/putting_it_all_together.md @@ -1,7 +1,6 @@ -Putting it all Together -=== +# Putting it All Together -Below you see what the complete parser class looks like: +The complete parser class appears below: # [C#](#tab/tabid-1) ```cs @@ -21,14 +20,10 @@ namespace Sdk.FileTypeSupport.Samples.Bil { class BilParser : AbstractBilingualFileTypeComponent, IBilingualParser, INativeContentCycleAware, ISettingsAware { - #region "global" private IPersistentFileConversionProperties _fileProperties; private XmlDocument _document; public event EventHandler Progress; - #endregion - #region "native content" - #region "set file properties" public void SetFileProperties(IFileProperties properties) { _fileProperties = properties.FileConversionProperties; @@ -39,18 +34,14 @@ namespace Sdk.FileTypeSupport.Samples.Bil fileInfo.FileConversionProperties = _fileProperties; Output.SetFileProperties(fileInfo); } - #endregion - #region "open file" public void StartOfInput() { OnProgress(0); _document = new XmlDocument(); _document.Load(_fileProperties.OriginalFilePath); } - #endregion - #region "close file" public void EndOfInput() { // done with the file @@ -61,10 +52,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil OnProgress(100); _document = null; } - #endregion - #endregion - #region "progress" protected virtual void OnProgress(byte percent) { if (Progress != null) @@ -72,9 +60,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil Progress(this, new ProgressEventArgs(percent)); } } - #endregion - #region "bilingual parser members" public IDocumentProperties DocumentProperties { get; @@ -86,9 +72,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil get; set; } - #endregion - #region "parse" public bool ParseNext() { // variables for the progress report @@ -105,16 +89,13 @@ namespace Sdk.FileTypeSupport.Samples.Bil return false; } - #endregion - #region "create paragraph units" // helper function for creating paragraph units private IParagraphUnit CreateParagraphUnit(XmlNode xmlUnit) { // create paragraph unit object IParagraphUnit paragraphUnit = ItemFactory.CreateParagraphUnit(LockTypeFlags.Unlocked); - // create segment pair object ISegmentPairProperties segmentPairProperties = ItemFactory.CreateSegmentPairProperties(); // assign the appropriate confirmation level to the segment pair @@ -131,7 +112,6 @@ namespace Sdk.FileTypeSupport.Samples.Bil paragraphUnit.Target.Add(trgSegment); } - #region "context" // create paragraph unit context string id = xmlUnit.SelectSingleNode("./@id").InnerText; if(xmlUnit.SelectSingleNode("type/@spec")!=null) @@ -142,21 +122,16 @@ namespace Sdk.FileTypeSupport.Samples.Bil } else { paragraphUnit.Properties.Contexts = CreateContext("Paragraph", id); } - #endregion - #region "comments" // extract comment (if applicable) if(xmlUnit.SelectSingleNode("comment")!=null) { paragraphUnit.Properties.Comments = CreateComment(xmlUnit.SelectSingleNode("comment").InnerText); } - #endregion return paragraphUnit; } - #endregion - #region "confirmation level" private ConfirmationLevel CreateConfirmationLevel(string BilStatus) { ConfirmationLevel sdlxliffLevel = ConfirmationLevel.Unspecified; @@ -179,9 +154,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil return sdlxliffLevel; } - #endregion - #region "create segment" // helper function for creating segment objects private ISegment CreateSegment(XmlNode segNode, ISegmentPairProperties pair) { @@ -201,9 +174,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil } return segment; } - #endregion - #region "create text" private IText CreateText(string segText) { ITextProperties textProperties = PropertiesFactory.CreateTextProperties(segText); @@ -211,9 +182,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil return textContent; } - #endregion - #region "process context" private IContextProperties CreateContext(string spec, string unitID) { // context info for type information, e.g. heading, paragraph, etc. @@ -248,14 +217,11 @@ namespace Sdk.FileTypeSupport.Samples.Bil return contextProperties; } - #endregion - #region "create tagpair" private ITagPair CreateTagPair(XmlNode item) { // create the start and the end tag IStartTagProperties startTag = PropertiesFactory.CreateStartTagProperties(item.Name); - #region "formatting" // apply character formatting to the start tag IFormattingGroup formattingGroup = PropertiesFactory.FormattingItemFactory.CreateFormatting(); startTag.Formatting = new FormattingGroup(); @@ -274,7 +240,6 @@ namespace Sdk.FileTypeSupport.Samples.Bil break; } startTag.Formatting = formattingGroup; - #endregion startTag.DisplayText=item.Name; startTag.CanHide = true; @@ -290,9 +255,7 @@ namespace Sdk.FileTypeSupport.Samples.Bil return tagPair; } - #endregion - #region "create comment" private ICommentProperties CreateComment(string commentText) { ICommentProperties commentProperties = PropertiesFactory.CreateCommentProperties(); @@ -301,25 +264,16 @@ namespace Sdk.FileTypeSupport.Samples.Bil return commentProperties; } - #endregion - - #region ISettingsAware Members public void InitializeSettings(Sdl.Core.Settings.ISettingsBundle settingsBundle, string configurationId) { //loading of filter settings } - #endregion - - #region IDispose Implementation - public void Dispose() { _document = null; } - - #endregion } } ``` diff --git a/apiconcepts/filetypesupport/reporting_problems.md b/apiconcepts/filetypesupport/reporting_problems.md index 206d5bbe94..99ea2354ad 100644 --- a/apiconcepts/filetypesupport/reporting_problems.md +++ b/apiconcepts/filetypesupport/reporting_problems.md @@ -1,166 +1,156 @@ -Reporting Problems -== +# Reporting problems -This topic covers different mechanisms that allows information to be communicated from the componentes of a filter to the application that hosts the File Type Support Framework during content processing. +This article explains how filter components can report problems to the application that hosts the File Type Support Framework during content processing. -Overview ---- -Since filters may be used in server-based scenarios, they cannot display information to users like normal Windows-based applications do, e.g. by using a ```MessageBox``` or directly updating the user interface of an application. Such behavior could cause the server process to hang, as there is no user to interact with the filter. +## Overview -If a file processing component comes across a show-stopper, it should throw an exception to abort further processing. The exception should have an explanatory error message that clearly points users to the problem and helps them fix it. It is recommended that you derive exceptions thrown for events that occur during content processing from [FileTypeSupportException](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.FileTypeSupportException.yml). +Filters can run in server-based scenarios, so they must not display UI such as a `MessageBox` or update an application's user interface directly. That behavior can block the server process because no user can respond. -A lot of events do not need to be treated as show-stoppers, but may still indicate that something is not correct. Such situations should not abort the processing, but may still be of interest to the user. The File Type Support Framework provides a message reporting mechanism that can be used to communicate with the user. This can be used by filter components to report non-fatal errors, warnings and notes. Such messages can also be associated with specific content locations. For exampe, in the **Messages** window of Var:ProductName you can double-click a message, which leads you directly to the location in the document in which a problem was found (e.g. a missing tag). +When a file processing component encounters a fatal error, it should throw an exception and stop processing. Use an error message that clearly explains the problem and helps users resolve it. When possible, derive content-processing exceptions from [FileTypeSupportException](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.FileTypeSupportException.yml). -The basic message reporting mechanism is the same for all components. It is accessible through the [IBasicMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml) interface, which is implemented by all message reporters provided by the framework. The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method takes an optional ```locationDescription``` (string) parameter that allows the component to provide a textual description of the location that the message refers to. Showing the text (e.g. in a window or message box) can help users find the relevant location in the document. This mechanism can be useful when the component (for whatever reason) is unable to provide exact coordinates to the associated content. +Some events do not justify aborting processing, but users may still need to see them. The File Type Support Framework provides a message reporting mechanism for non-fatal errors, warnings, and notes. Components can also associate messages with specific content locations. In the **Messages** window of Var:ProductName, for example, users can double-click a message to jump to the location where the framework detected the issue, such as a missing tag. -As mentioned before, messages may be associated with detailed location information, which can be used by an application like the Var:ProductName to allow users to navigate, e.g. to a particular segment in the editor in which a problem has been identified. How to associate a message with precise location information depends on the type of component used. The mechanism to translate locations associated with messages also differs depending on where in the content processing chain the message is was generated (though this is transparent to the filter component and to the host application). Issues related to message reporting for each component type are covered in separate sections below. +All framework-provided message reporters implement [IBasicMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml). The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method accepts an optional `locationDescription` parameter. Use this parameter when a component cannot provide exact coordinates but can still describe the relevant location in a way that helps users find it. -Exact location information can represent either a single spot or a range of content. Ranges are reported by specifying separate "from" and an "up to" locations. The "up to" location is optional. If it is omitted, the location is interpreted as a single spot. +Components can also attach precise location information. Applications such as Var:ProductName can use that information to navigate to a segment or another relevant location in the editor. The exact mechanism depends on the component type. The framework also translates message locations differently depending on where the component reported the message, although that translation remains transparent to both the filter component and the host application. The following sections describe each component type. -All message locations are translated by the framework into a unified location representation, in the form of [IMessageLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IMessageLocation.yml) instances. An application can e.g. pass this to the editor to get a corresponding location inside the document, to provide click-on message functionality. +Exact location information can identify a single spot or a range of content. To report a range, provide separate `from` and `up to` locations. The `up to` location is optional. If you omit it, the framework treats the location as a single spot. -The locations can also be serialized for use with batch processing (at the time of writing this mechanism was not implemented). +The framework translates all message locations into a unified representation through [IMessageLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IMessageLocation.yml). An application can pass that object to the editor to resolve the corresponding document location and enable click-on message behavior. -File Sniffer --- +The framework can also serialize locations for batch processing, although this mechanism was not implemented at the time of writing. -A [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml) receives an instance of a [INativeTextLocationMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeTextLocationMessageReporter.yml) in the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method. This can be used to communicate relevant information with associated locations to the File Type Support Framework (and ultimately to the user). +## File sniffer -The file sniffer's general purpose is to determine if the specified file is supported or not. Under normal circumstances, file sniffers would not report issues related to the file. This can sometimes be confusing to users, since there may be another filter that properly supports the file. However, in some cases it is helpful for the file sniffer to inform users, e.g. if the file is locked, or if the file type is currect, but cannot be supported for some reason (e.g. a DOC file that contains unaccepted changes). +An [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml) receives an [INativeTextLocationMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeTextLocationMessageReporter.yml) in the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method. The sniffer can use this reporter to send relevant information and associated locations to the File Type Support Framework. -A file sniffer is not expected to throw exceptions. If a file sniffer throws an exception, this normally indicates a bug in the file sniffer. Exceptions thrown by file sniffers are handled by the File Type Support Framework and reported as warnings through the message reporting mechanism in the same way as messages reported by file sniffers through the message reporter passed to the Sniff() method. If a file sniffer throws an exception, the file is considered as not supported by the corresponding File Type Component Builder. +The main purpose of a file sniffer is to determine whether it supports a file. Under normal circumstances, a sniffer should not report issues for unsupported files because another filter might support the same file correctly. In some cases, however, a warning helps users. Examples include a locked file or a file that matches the file type but still cannot be processed, such as a DOC file that contains unaccepted changes. -Locations for messages from a file sniffer are reported using [NativeTextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.NativeTextLocation.yml) instances, which ultimately represent 1-based line and offset numbers. +A file sniffer should not throw exceptions. If it does, the framework usually treats that exception as a bug in the sniffer. The File Type Support Framework catches the exception, reports it as a warning through the same message reporting mechanism, and treats the file as unsupported by the corresponding File Type Component Builder. -The locations will only be used if the file has actually been opened. Messages from all invoked file sniffers may be shown to the user, regardless of whether they originate from the file sniffer that is part of the File Type Component Builder that was ultimately used to process the file. Since this can potentially be confusing to users, it is recommended that file sniffers only report issues that are very likely of interest to the user. (In real-life scenarios this is typically not a problem, as for most file types only a single file sniffer is invoked.) +File sniffers report locations with [NativeTextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.NativeTextLocation.yml) instances, which use 1-based line and offset numbers. -Upon opening a file the locations is automatically translated by the File Type Support Framework, so that they can be used to generate click-on messages in an editor. The File Type Support Framework does this by listening to the output from the native file parser and by inserting location markers into the content stream at the line and offset numbers that correspond to the locations for messages reported by file sniffers. The line and offsets are determined from the literal text and tag content output by the parser to the native API. +The framework only uses these locations if it actually opens the file. Users may still see messages from all invoked file sniffers, even if the selected File Type Component Builder came from a different sniffer. To avoid confusion, report only issues that users are very likely to care about. In practice, this usually works well because most file types invoke only one sniffer. -From the nature of this mechanism it is obvious that the locations reported by the file sniffer may not correspond exactly to the correct locations in the bilingual content. File tweakers might have altered the native file before it was processed by the native parser. Moreover, the native parser may not emit all literal tag and text content through the native API, or it may choose to emit content in a different order than it appears in the native file. Message locations from file sniffers work best with file types in which all content in the native file is preserved and "marked up" as tags and text by the parser. For other file types it may be more suitable to provide a location description instead of an exact location. +When the framework opens a file, it translates the reported locations automatically so the editor can support click-on messages. The File Type Support Framework listens to the native file parser output and inserts location markers into the content stream at the reported line and offset numbers. It derives those positions from the literal text and tag content that the parser emits through the native API. -Here is a code example that shows how to report a warning from a file sniffer: +These translated locations may not always match the final bilingual content exactly. A file tweaker may change the native file before the parser runs. The parser may also omit some literal text or tag content, or emit content in a different order than the native file. File sniffer locations work best when the parser preserves the native file content and represents it as tags and text. If that does not apply to the file type, provide a location description instead of an exact location. + +The following example reports a warning from a file sniffer: -# [C#](#tab/tabid-1) ```cs void ReportWarning(string message, int lineNumber, int offset, INativeTextLocationMessageReporter messageReporter) { NativeTextLocation from = new NativeTextLocation(lineNumber, offset); - messageReporter.ReportMessage(this,"SDK Sample", ErrorLevel.Warning, message, from, null); + messageReporter.ReportMessage(this, "SDK Sample", ErrorLevel.Warning, message, from, null); } ``` -*** -File Tweaker --- +## File tweaker -File tweakers are invoked in order to alter the native file before processing with the native parser, and/or to alter the translated native file after processing by the file writer. As such they do not have access to the native content stream or the bilingual content model. So, similar to the file sniffers the file tweakers must report message locations in the form of line and offset numbers in the native file content. +File tweakers can modify the native file before the native parser processes it, or modify the translated native file after the file writer finishes. Because they do not access the native content stream or the bilingual content model directly, they must report locations as line and offset numbers in the native file. -During initialization the File Type Support Framework sets the [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFileTweaker.yml#Sdl_FileTypeSupport_Framework_NativeApi_IFileTweaker_MessageReporter) property on the file tweaker. The file tweaker can use this to report messages with associated locations to the framework. +During initialization, the File Type Support Framework sets the [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFileTweaker.yml#Sdl_FileTypeSupport_Framework_NativeApi_IFileTweaker_MessageReporter) property on the file tweaker. The tweaker can then use that reporter to send messages and associated locations to the framework. -For pre-tweaking the File Type Support Framework treats file tweaker message locations similar to locations for messages reported by file sniffers, i.e. location markers are inserted into the native content stream at locations corresponding to the line and offset numbers. +For pre-tweaking, the File Type Support Framework handles file tweaker locations in the same way that it handles file sniffer locations. It inserts location markers into the native content stream at the reported line and offset numbers. -For post-tweaking the File Type Support Framework tracks the line and offset numbers for literal text and tag content passed to the native file writer, and uses this information to translate the location into a corresponding place in the native content stream. This is then translated into bilingual content locations by attempting to determine which paragraph unit and segment the location refers to, and how many characters into the segment the location appears in. +For post-tweaking, the framework tracks the line and offset numbers for literal text and tag content that the native file writer receives. It uses that information to map the reported location to a position in the native content stream, and then tries to translate that position into a corresponding paragraph unit, segment, and character offset in the bilingual content. -Like with file sniffers, the locations reported by file tweakers may not translate correctly into bilingual content locations, for pretty much the same reasons. Also, the message locations works best with file types in which the entire native content is present in the form of tags and text in the native content stream. If this is not the case for the file type being processed, file tweakers may use location descriptions rather than exact locations. +As with file sniffers, file tweaker locations may not always translate correctly into bilingual content locations. They work best when the native content stream contains the full native file content as tags and text. If that does not apply to the file type, use a location description instead of exact coordinates. -Here is a code example that shows how to communicate information from a file tweaker: +The following example reports a message from a file tweaker: -# [C#](#tab/tabid-2) ```cs void ReportMessage(string message, ErrorLevel severity, int lineNumber, int offset, INativeTextLocationMessageReporter messageReporter) { NativeTextLocation from = new NativeTextLocation(lineNumber, offset); - messageReporter.ReportMessage(this,"SDK Sample", severity, message, from, null); + messageReporter.ReportMessage(this, "SDK Sample", severity, message, from, null); } ``` -*** -Native File Parser and Native Content Processor for Extraction and Generation --- +## Native file parser and native content processor for extraction and generation + +Components that generate output through the native API can mark locations in the native content by creating a [LocationMarkerId](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LocationMarkerId.yml) and calling [LocationMark](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_LocationMark_Sdl_FileTypeSupport_Framework_NativeApi_LocationMarkerId_). They can then pass those marker IDs as `from` and `up to` locations when they report a message through [INativeContentStreamMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentStreamMessageReporter.yml). The File Type Support Framework provides the message reporter through the component's [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFileTweaker.yml#Sdl_FileTypeSupport_Framework_NativeApi_IFileTweaker_MessageReporter) property. -Components that generate output through the native API can mark locations in the native content by creating a new [LocationMarkerId](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.LocationMarkerId.yml) and and calling [LocationMark](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_LocationMark_Sdl_FileTypeSupport_Framework_NativeApi_LocationMarkerId_) to output the marker. Locations marked in this way can be associated with messages reported on the [INativeContentStreamMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentStreamMessageReporter.yml) interface by passing the location marker ID as a "from" or "up to" location. The message reporter implementation is provided by the File Type Support Framework to these components through their implementation of the [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFileTweaker.yml#Sdl_FileTypeSupport_Framework_NativeApi_IFileTweaker_MessageReporter) property. +During extraction, the framework propagates location markers into the bilingual content model as [ILocationMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILocationMarker.yml) instances. This approach provides highly reliable locations and often still points to the correct place even after users edit the text extensively. -For messages reported during extraction (parsing) the location marks are propagated into the bilingual content model as [ILocationMarker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.ILocationMarker.yml) instances, which are referenced explicitly as the bilingual locations. This provides very reliable locations, which often point to the correct locations even after the user has edited the text exensively. +During generation, the framework detects location markers in the native content stream and translates them into corresponding locations in the bilingual content model. In this case, the resulting bilingual locations usually are not location marker objects. This translation is less direct because the native API content can differ significantly from the bilingual API content. For example, the framework may merge tag pairs automatically or clone source content into the target for untranslated parts. -For messages reported by native content processors during generation (writing) the File Type Support Framework detects the location marks in the native content stream and does its utmost to translate them into corresponding locations in the bilingual content model. In this case the locations in the bilingual content model will typically NOT be location marker objects. The translation from the native generation into the bilingual content that is implemented in the File Type Support Framework is not always straightforward. The native API content may look quite different from the bilingual API content due to automatic merging of tag pairs and cloning of source content into the target for parts that have not yet been translated, etc. The File Type Support Framework attempts to work around the uncertainties as much as possible by "anchoring" the location to the nearest preceding segment or paragraph boundary as detected in the native generation API. The approximate location is determined by counting the number of characters in the native text and tags between the last segment or paragraph boundary and the location marker in the native content stream. This value is then used with the bilingual content model to locate the corresponding paragraph unit and (if possible) segment. The location inside the paragraph or segment is determined by iterating through the segment content and counting characters in the text and tag properties. The bilingual location is restricted to the determined segment, even if it does not contain "enough" characters. That way the location should end up in the correct row in the editor in almost all cases. Therefore, locations reported by native content processors during generation are usually reasonably accurate, but cannot be relied on quite as much as locations reported by parsing. If the user edits the text in the same segment the locations may no longer be correct, however locations in neighboring segments should not be affected. +To improve accuracy, the File Type Support Framework anchors the reported location to the nearest preceding segment or paragraph boundary detected in the native generation API. It then counts characters in the native text and tags between that boundary and the location marker. Next, it uses that count to find the corresponding paragraph unit and, when possible, the segment in the bilingual content model. Finally, it determines the location inside that paragraph or segment by counting characters in text and tag properties. The framework restricts the final location to the resolved segment, even if the character count does not map perfectly. As a result, generation-time locations are usually accurate enough to identify the correct editor row, but they are less reliable than parsing-time locations. If a user edits the same segment, the location may become inaccurate. Edits in neighboring segments should not affect it. -Here is a code example that shows how a 'suspicious' tag could be reported by a native content processor. The native content processor in this example would be derived from ```AbstractNativeExtractionContentProcessor``` or ```AbstractNativeGenerationContentProcessor``` and the function below overrides the processing of placeholder tags to check for tags that look 'suspicious' and report those to the user. +The following example reports a suspicious tag from a native content processor. This processor derives from `AbstractNativeExtractionContentProcessor` or `AbstractNativeGenerationContentProcessor` and overrides placeholder tag handling: -# [C#](#tab/tabid-3) ```cs -public void PlaceholderTag(IPlaceholderTagProperties tagInfo) - { +public override void PlaceholderTag(IPlaceholderTagProperties tagInfo) +{ if (IsSuspiciousTag(tagInfo)) { - // insert location marks around the tag - LocationMarkerId fromId = new LocationMarkerId(); - LocationMarkerId uptoId = new LocationMarkerId(); + LocationMarkerId fromId = new LocationMarkerId(); + LocationMarkerId uptoId = new LocationMarkerId(); + + LocationMark(fromId); + base.PlaceholderTag(tagInfo); + LocationMark(uptoId); - // report the message - MessageReporter.ReportMessage(this, "SDK Sample", ErrorLevel.Warning, "Suspicious tag!", fromId, uptoId); + MessageReporter.ReportMessage(this, "SDK Sample", ErrorLevel.Warning, "Suspicious tag!", fromId, uptoId); + return; } - } + + base.PlaceholderTag(tagInfo); +} ``` -*** -Bilingual Content Processor, Bilingual Parser and Bilingual Writer --- +## Bilingual content processor, bilingual parser, and bilingual writer + +Components that work directly with the bilingual content model can associate message locations with either the source or the target content. The [IBilingualContentMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml) interface accepts [TextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.TextLocation.yml) instances for the `from` and `up to` locations. -Components that work directly with the bilingual content model can associate message locations directly with either the source or the target content. The [IBilingualContentMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualContentMessageReporter.yml) interface takes [TextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.TextLocation.yml) instances for the "from" and "up to" locations. The [TextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.TextLocation.yml) class allows you to directly reference a text position inside the bilingual content model. It has several constructors. The one that you may find most convenient is the one that takes a single ````IMarkupData```` item as the location to reference. +The [TextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.TextLocation.yml) class lets you reference a text position directly in the bilingual content model. It provides several constructors. One convenient option accepts a single `IMarkupData` item as the referenced location. -It is important to note that the use of [TextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.TextLocation.yml) instances means that components that report messages do not need to alter the content of the bilingual object model. This does not require the use of location markers. +Because components can report messages with `TextLocation`, they do not need to alter the bilingual object model. They also do not need location markers. -The main component of the [TextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.TextLocation.yml) is a [Location](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.Location.yml), which allows you to reference locations before and after items in the content model. +At its core, [TextLocation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.TextLocation.yml) wraps a [Location](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.Location.yml), which lets you reference positions before and after items in the content model. -The locations in the bilingual content model is probably the most reliable message location reference method, as it involves much less 'guesswork' for the File Type Support Framework to pinpoint the location. +Direct bilingual locations usually provide the most reliable message references because the File Type Support Framework does far less translation work. -Here is a code example that shows how a string that contains a problem could be reported by a bilingual content processor. +The following example reports problematic text from a bilingual content processor: -# [C#](#tab/tabid-4) ```cs void ReportOffendingText(IText textItem, int startOffset, int numberOfCharacters) { TextLocation from = new TextLocation(textItem, startOffset); TextLocation upto = new TextLocation(textItem, startOffset + numberOfCharacters); - // report the message - MessageReporter.ReportMessage(this,"SDK Sample", ErrorLevel.Warning, "Inappropriate expression!", from, upto); + MessageReporter.ReportMessage(this, "SDK Sample", ErrorLevel.Warning, "Inappropriate expression!", from, upto); } ``` -*** -Native File Writer --- +## Native file writer -A native file writer receives content on the native input stream. However, the output does not occur through an API provided by the File Type Support Framework, it rather writes directly into the output file that it is creating. For this reason native file writers must report message locations through the [INativeTextLocationMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeTextLocationMessageReporter.yml) instance provided by the framework through the [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFileTweaker.yml#Sdl_FileTypeSupport_Framework_NativeApi_IFileTweaker_MessageReporter) property. +A native file writer receives content on the native input stream, but it writes output directly to the file that it creates instead of writing through an API provided by the File Type Support Framework. For that reason, native file writers must report locations through the [INativeTextLocationMessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeTextLocationMessageReporter.yml) instance that the framework provides through the [MessageReporter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IFileTweaker.yml#Sdl_FileTypeSupport_Framework_NativeApi_IFileTweaker_MessageReporter) property. -The message locations are reported as line and offset numbers that refer to the text and tag content that is passed to the writer's implementation of the native content handler interface. These locations are translated by the File Type Support Framework into locations in the bilingual content model by "anchoring" them to the nearest available paragraph and segment boundaries processed through the writer. +Native file writers report locations as line and offset numbers that refer to the text and tag content passed to the native content handler implementation. The File Type Support Framework translates those locations into bilingual content locations by anchoring them to the nearest available paragraph and segment boundaries that the writer processes. -If a native file writer encounters a serious error because of which the output file cannot be generated, it should throw an exception. The File Type Support Framework automatically catches exceptions thrown by native file writers and generates a message for the exception with an associated location that points to the content that was being processed by the file writer, and then the exception again. Provided that the exception is thrown at the time that the 'problematic' content is passed to the native file writer, this should yield a valid location associated with the message. So, if that is the case, the writer does not need to explicitly generate a message. On the other hand, it often happens that the 'problematic' content comes up earlier in the content stream, in which case the location associated with the automatically generated message may be misleading. In such a case, it is recommended that file writers report the error with the appropriate message location before throwing the exception. +If a native file writer encounters a fatal error and cannot generate the output file, it should throw an exception. The File Type Support Framework catches exceptions from native file writers and automatically generates a message with an associated location that points to the content being processed when the exception was thrown. If the writer throws the exception exactly when it processes the problematic content, that generated location is usually sufficient. If the problematic content appears earlier in the stream, however, the generated location can mislead users. In that case, report the error explicitly with the correct location before you throw the exception. -The File Type Support Framework provides a [INativeLocationTracker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeLocationTracker.yml) implementation to the writer by setting the [LocationTracker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileWriter_LocationTracker) property during initialization of the writer. The location tracker provides a convenient way for the writer to determine the locations of the content that it is currently processing. +During initialization, the File Type Support Framework also sets the [LocationTracker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileWriter_LocationTracker) property with an [INativeLocationTracker](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeLocationTracker.yml) implementation. Use that tracker to determine the location of the content currently being processed. -Below you find a code example that shows how an unexpected start tag could be reported by a native file writer: +The following example reports an unexpected start tag from a native file writer: -# [C#](#tab/tabid-5) ```cs public override void InlineStartTag(IStartTagProperties tagInfo) { if (!IsExpectedStartTag(tagInfo)) { - // report the tag and ignore it NativeTextLocation from = GetLocationBeforeCurrent(); NativeTextLocation upto = GetLocationAfterCurrent(); - MessageReporter.ReportMessage(this,"SDK Sample", ErrorLevel.Error, "Unexpected tag pair!", from, upto); + MessageReporter.ReportMessage(this, "SDK Sample", ErrorLevel.Error, "Unexpected tag pair!", from, upto); return; } - // process as normal ProcessStartTag(tagInfo); } ``` -** >[!NOTE] > diff --git a/apiconcepts/filetypesupport/sample_projects.md b/apiconcepts/filetypesupport/sample_projects.md index 3e73ee4448..0baffc4799 100644 --- a/apiconcepts/filetypesupport/sample_projects.md +++ b/apiconcepts/filetypesupport/sample_projects.md @@ -1,14 +1,12 @@ -SampleProjects -== +# Sample Projects This SDK contains one native filter sample project. -Sample Projects: Native Filters --- +## Sample Projects: Native Filters -In the sample projects folder of this SDK you will find the following sub-folder: +In the sample projects folder of this SDK, you will find the following sub-folder: -* **SimpleTextFilter**: Contains the project for the simple text filter, which is explained in this programming guide +* **SimpleTextFilter**: This project contains the simple text filter, which this programming guide explains. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/saving_to_different_file_types.md b/apiconcepts/filetypesupport/saving_to_different_file_types.md deleted file mode 100644 index 53256580ca..0000000000 --- a/apiconcepts/filetypesupport/saving_to_different_file_types.md +++ /dev/null @@ -1,15 +0,0 @@ -Saving to different file types -===== - -From the intermediary format (currently mostly SDLXliff), users need to be able to generate a target document, which will often be the native format (e.g. DOC, PTT, etc.). In some cases, users also need to be able to generate another bilingual intermediary format such as TTX or ITD. This is the case when Var:ProductName is used to process TTX/ITD files that came from Trados 2007 or SDLX 2007 and the users of Var:ProductName need to deliver TTX/ITD files for further processing in an SDL Trados 2007/SDLX 2007-based supply chain. - -When a user of Var:ProductName is required to do a translation, which can then be further processed by a user of Trados 2007 or SDLX 2007, he/she will have to proceed in the following way: - -* Pre-process the native file in Trados 2007, e.g. by opening it in TagEditor and by saving it as TTX (TradosTag) -* Open the resulting TTX file(s) in Var:ProductName. While the TTX or ITD files are processed in Var:ProductName, they are saved in the intermediary format used by Var:ProductName just like any other (native) file (e.g. in SDLXliff). - - -If you proceed as described above, you can generate a TTX/ITD document from the intermediary format (e.g. SDLXliff). Alternatively, you can also generate the original native format (e.g. DOC). When the user selects the **Save Target As** command, a dialog box opens which lets users decide whether to save the file as TTX/ITD (for further processing in Trados 2007 or SDLX 2007) or whether the original file format should be generated. -When you process a TTX (or ITD) file in Var:ProductName, you have a choice between generating a TTX or the original document format. The latter requires you to have the original document (e.g. DOC) in the same folder as the TTX file. The reason for this is that TTX uses the original document as dependency file, which is **not** embedded in the TTX document itself. - - diff --git a/apiconcepts/filetypesupport/segmentation_hints.md b/apiconcepts/filetypesupport/segmentation_hints.md index 2e48cb7d9b..1ab7775a7b 100644 --- a/apiconcepts/filetypesupport/segmentation_hints.md +++ b/apiconcepts/filetypesupport/segmentation_hints.md @@ -1,9 +1,8 @@ -Segmentation Hints -== +# Segmentation Hints -The [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml) property is used to specify the required behavior of a tag placeholder or tag pair if it it appears on a segment boundary (leading or trailing). Such tags are moved by the segmentation engine to the content outside the segment boundaries, which is hidden and has to be displayed by in the specific editor view (when setting the display filter to 'all content'). +The [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml) property specifies the required behavior of a tag placeholder or tag pair that appears on a segment boundary (leading or trailing). The segmentation engine moves such tags to content outside the segment boundaries. This content is hidden by default but displays in the editor when you set the display filter to "all content". -The [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml) property setting does not change the behavior of tags that are not located on the segment boundaries and it is used only by the segmentation engine during the initial conversion of the native file to SDLXliff format. [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields) may be set to following values: +The segmentation engine only applies the [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml) property during initial conversion of the native file to SDLXliff format. It does not affect tags that are not located on segment boundaries. Set [SegmentationHint](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields) to one of the following values: * [Undefined](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields) * [MayExclude](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SegmentationHint.yml#fields) diff --git a/apiconcepts/filetypesupport/settings_page_example.md b/apiconcepts/filetypesupport/settings_page_example.md index 3d4ad39e27..f750b90e07 100644 --- a/apiconcepts/filetypesupport/settings_page_example.md +++ b/apiconcepts/filetypesupport/settings_page_example.md @@ -1,7 +1,6 @@ -Settings Page Example -== +# Settings Page Example -An example of a settings page is shown below which sets the sub-content processor [FileTypeConfiguration](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeConfigurationAware.yml) Ids on the control: +The following example shows a settings page that sets the sub-content processor [FileTypeConfiguration](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeConfigurationAware.yml) IDs on the control: # [C#](#tab/tabid-1) ```cs @@ -11,55 +10,39 @@ using Sdl.Sdk.Snippets.Native; namespace Sdk.FileTypeSupport.Samples.SimpleText.WinUI { /// - /// This class controls the plug-in user interface. It controls what happens, for example, - /// when the user clicks the button in the user interface for resetting the control elements - /// to their default values. This class is referenced in the file type definition. Without - /// this reference in the SDLFILETPYE file, the plug-in user interface would not be available - /// to the end user. + /// This class controls the plug-in user interface. It handles what happens when the user clicks + /// the Reset to Defaults button in the user interface. This class is referenced in the file type definition. + /// Without this reference in the SDLFILETYPE file, the plug-in user interface is not available to the end user. /// - #region "SettingsPagePlugin" [FileTypeSettingsPage(Id = "SimpleText_Settings", Name = "Settings_Name", Description = "Settings_Description")] - #endregion - #region "ClassDeclaration" class SettingsPage : AbstractFileTypeSettingsPage - #endregion { /// - /// Triggered, when the user clicks the button Reset to Defaults button in - /// Trados Studio. Restores the default check box state, which should - /// be Checked (i.e. product code strings should be locked). + /// Called when the user clicks the Reset to Defaults button in Trados Studio. + /// Restores the default checkbox state (product code strings should be locked). /// - #region "ResetToDefaults" public override void ResetToDefaults() { base.ResetToDefaults(); Control.UpdateControl(); - // Set sub-content Ids on Control + // Set sub-content IDs on Control Control.FileTypeConfigurationIds = SubContentFileTypeConfigurationIds; - } - #endregion + } /// - /// Triggered when the user raises the plug-in UI, whose controls (in this case the check box - /// for locking product code strings) will then be set according to the values stored in - /// the settings bundle. + /// Called when the user opens the plug-in UI. Sets the control values according to the settings + /// stored in the settings bundle. /// - /// - #region "Refresh" public override void Refresh() { base.Refresh(); Control.UpdateControl(); - // Set sub-content Ids on Control + // Set sub-content IDs on Control Control.FileTypeConfigurationIds = SubContentFileTypeConfigurationIds; } - #endregion - - } } ``` -*** >[!NOTE] > diff --git a/apiconcepts/filetypesupport/static_modifying_the_file_type_component_builder.md b/apiconcepts/filetypesupport/static_modifying_the_file_type_component_builder.md index 9d1059b4c8..d35a04839c 100644 --- a/apiconcepts/filetypesupport/static_modifying_the_file_type_component_builder.md +++ b/apiconcepts/filetypesupport/static_modifying_the_file_type_component_builder.md @@ -1,19 +1,16 @@ -Modifying the File Type Component Builder -== +# Modifying the file type component builder -This chapter outlines the quickest way to implement an internal static document preview function. +This article shows how to add an internal static document preview. -Add the Static Preview Name to the Resources --- +## Add the static preview name to the resources -To implement the static preview we first need to make a few additions to the File Type Component Builder. In the first step, define the preview name in the resources file. This is the name that will be shown later in the combo box of the preview window of Var:ProductName. Add the following entries to the resources file, which are going to be referenced in the File Type Component Builder later: +Start by defining the preview name in the resources file. Var:ProductName displays this name in the Preview window combo box. The File Type Component Builder references these resource entries later. ![InternalStaticPreviewName](images/InternalStaticPreviewName.jpg) -Add the Static Internal Preview Set Reference --- +## Add the static internal preview set reference -In the next step add the following preview set method for the static internal preview into the File Type Component Builder file. Note that the method references the preview name that you previously defined in the resources file. +Next, add the following preview set definition to the File Type Component Builder. This code references the preview name that you defined in the resources file. # [C#](#tab/tabid-1) ```cs @@ -38,12 +35,15 @@ if (targetControlPreviewType1 != null) } previewFactory.GetPreviewSets(null).Add(internalStaticPreviewSet); ``` -*** +## Define the preview control -Define the Preview Control --- +An internal preview needs a control that can display document content. You can create a custom preview control, and you will do that later for the dynamic real-time preview. See [Adding a Preview UI Control](adding_a_preview_ui_control.md). -For an internal preview you require a control element that can display the document content. You could add your own custom preview control element. This is actually what we are going to do later, when we implement the dynamic real-time preview (see [Adding a Preview UI Control](adding_a_preview_ui_control.md)). However, to keep things as simple as possible for now, we will leverage the built-in Web browser control that is integrated in Var:ProductName. As we are dealing with a simple text format, we can easily use the built-in Web browser control to generate the preview output. To 'tell' the file type plug-in that it should leverage the built-in Web browser control, make an addition to the File Type Component Builder. You can add the new method just below the Notepad preview control, which you defined for the external preview functionality (see [Implementing an External File Preview](implementing_an_external_file_preview.md)). Note that the **id** of the object corresponds to the name of the preview set that you added in the previous step, and must be preceded by a **PreviewControl_** prefix to be properly recognized. +For this static preview, use the built-in web browser control in Var:ProductName. Because this sample uses a simple text format, the built-in control can render the preview output without extra setup. + +To register the built-in web browser control, add the following method to the File Type Component Builder. Place it below the Notepad preview control that you added for the external preview. See [Implementing an External File Preview](implementing_an_external_file_preview.md). + +The object **id** must match the preview set name from the previous step. It must also start with the **PreviewControl_** prefix. # [C#](#tab/tabid-2) ```cs @@ -74,18 +74,19 @@ public virtual IAbstractPreviewControl BuildPreviewControl(string name) } } ``` -*** +## Define the preview writer -Define the Preview Writer --- +The preview control also needs a writer that supplies the displayed content. You could reuse the file writer that you already implemented for the file type plug-in and the external preview. See [Implementing an External File Preview](implementing_an_external_file_preview.md). -Naturally, you need a writer component to fill the preview control element with content to display. You could, of course, use the file writer class, which you have already implemented in your file type plug-in and which you also leveraged for the external preview (see [Implementing an External File Preview](implementing_an_external_file_preview.md)). However, if you did this, the output in the internal Web browser control would look as shown below: +However, if you reuse that writer, the internal web browser control produces output like this: ![StaticPreviewNotGood](images/StaticPreviewNotGood.jpg) -As you can see, if we re-used the existing file writer, the internal preview would not add much value to our file type plug-in. First, the inline tags are shown as normal text and no character formatting is applied in this preview. Also, the preview shows all non-translatable strings, which will usually not be very useful for this type of preview. We should therefore implement another writer component that generates a nicely layouted HTML output in the internal preview. This sound like a cosmetic issue, but the preview should be visually appealing to end users and ideally give them an idea of the document layout to provide additional value. +This output adds little value. It shows inline tags as plain text. It also applies no character formatting. In addition, it includes all non-translatable strings, which usually do not help in this type of preview. -Before we actually implement our new preview writer component (see [Implementing the Preview Writer](implementing_the_preview_writer.md)), we add the method for this new component to the File Type Component Builder. You can make this addition below the object for the external preview writer (see chapter [Implementing an External File Preview](implementing_an_external_file_preview.md)). In the next chapter you will learn how to implement the new preview file writer class, which generates the preview output. +Instead, implement a second writer that generates formatted HTML for the internal preview. A better preview improves readability and gives end users a clearer sense of the document layout. + +Before you implement the new preview writer, add the following method to the File Type Component Builder. Place it below the object for the external preview writer. See [Implementing an External File Preview](implementing_an_external_file_preview.md). The next article explains how to implement the preview file writer class. See [Implementing the Preview Writer](implementing_the_preview_writer.md). # [C#](#tab/tabid-3) ```cs @@ -113,16 +114,10 @@ public virtual IAbstractGenerator BuildAbstractGenerator(string name) return null; } ``` -*** - -See Also --- - - - -[Implementing the Preview Writer](implementing_the_preview_writer.md) +## See also -[Implementing the File Writer](implementing_the_file_writer.md) +- [Implementing the Preview Writer](implementing_the_preview_writer.md) +- [Implementing the File Writer](implementing_the_file_writer.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/sub_content_component_builder.md b/apiconcepts/filetypesupport/sub_content_component_builder.md index 107a256299..6be42477aa 100644 --- a/apiconcepts/filetypesupport/sub_content_component_builder.md +++ b/apiconcepts/filetypesupport/sub_content_component_builder.md @@ -1,7 +1,6 @@ -Sub Content Component Builder -== +# Sub Content Component Builder -An example of a sub-content component builder is shown below - note the implementation of [ISubContentComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml) +The following example implements [ISubContentComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml): # [C#](#tab/tabid-1) ```cs @@ -21,37 +20,31 @@ namespace Sdk.Snippets.Native Description = "SimpleText_FilterComponentBuilderExtension_Description")] class SimpleTextSubContentComponentBuilder : IFileTypeComponentBuilder, ISubContentComponentBuilder { - // AbstractGenerator not supported by SubContentComponentBuilder public IAbstractGenerator BuildAbstractGenerator(string name) { return null; } - // AdditionalGeneratorsInfo not supported by SubContentComponentBuilder public IAdditionalGeneratorsInfo BuildAdditionalGeneratorsInfo(string name) { return null; } - // BilingualGenerator not supported by SubContentComponentBuilder public IBilingualDocumentGenerator BuildBilingualGenerator(string name) { return null; } - // FileExtractor not supported by SubContentComponentBuilder public IFileExtractor BuildFileExtractor(string name) { return null; } - // FileGenerator not supported by SubContentComponentBuilder public IFileGenerator BuildFileGenerator(string name) { return null; } - // FileSniffer not supported by SubContentComponentBuilder public INativeFileSniffer BuildFileSniffer(string name) { return null; @@ -76,31 +69,26 @@ namespace Sdk.Snippets.Native return info; } - // PreviewApplication not supported by SubContentComponentBuilder public IAbstractPreviewApplication BuildPreviewApplication(string name) { return null; } - // PreviewControl not supported by SubContentComponentBuilder public IAbstractPreviewControl BuildPreviewControl(string name) { return null; } - // PreviewSetsFactory not supported by SubContentComponentBuilder public IPreviewSetsFactory BuildPreviewSetsFactory(string name) { return null; } - // QuickTagsFactory not supported by SubContentComponentBuilder public IQuickTagsFactory BuildQuickTagsFactory(string name) { return null; } - // VerifierCollection not supported by SubContentComponentBuilder public IVerifierCollection BuildVerifierCollection(string name) { return null; @@ -124,7 +112,6 @@ namespace Sdk.Snippets.Native } } ``` -*** >[!NOTE] > diff --git a/apiconcepts/filetypesupport/sub_content_overview.md b/apiconcepts/filetypesupport/sub_content_overview.md index 88521f0375..b49f2269e3 100644 --- a/apiconcepts/filetypesupport/sub_content_overview.md +++ b/apiconcepts/filetypesupport/sub_content_overview.md @@ -1,30 +1,35 @@ -Sub Content Overview -== +# Sub Content Overview -The File Type Support Framework allows users to create sub-content filters or processors which handle content which is of a different format to the main content. For example, an XML file may contain a CDATA section which in turn contains HTML markup. The main XML filter processes the XML until it hits the CDATA section. It then passes the contents to the CDATA section to the framework and asks it to process this using an appropriate sub-content processor (in this example, an HTML processor) +The File Type Support Framework allows you to create sub-content filters or processors that handle content in a different format from the main content. For example, an XML file may contain a CDATA section with HTML markup. The main XML filter processes the XML until it encounters the CDATA section, then passes the contents to the framework for processing by an appropriate sub-content processor (such as an HTML processor). -Handling SubContent in the File Type Support Framework --- +## Handling Sub-Content in the File Type Support Framework -The File Type Support Framework supports handling of sub-content in the following manner: +The File Type Support Framework handles sub-content in the following manner: -The main parser must be able to determine which of its content is to be treated as sub-content. In order to push the sub-content to the framework, it must implement the [ISubContentPublisher](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml) interface. This interface defines an event named [ProcessSubContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentPublisher_ProcessSubContent) which is raised whenever the main parser wishes to pass off subcontent to the File Type Support Framework. The main parser populates the properties of the [ProcessSubContentEventArgs](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ProcessSubContentEventArgs.yml) and then raises the event. The File Type Support Framework takes the ID of the sub-content processor from the event arguments and uses this to set up this processor to handle the sub-content. +The main parser must identify which content is sub-content and implement the [ISubContentPublisher](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml) interface to send sub-content to the framework. This interface provides the [ProcessSubContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentPublisher_ProcessSubContent) event. When the main parser detects sub-content, it populates the [ProcessSubContentEventArgs](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ProcessSubContentEventArgs.yml) properties and raises the event. The framework uses the sub-content processor ID from the event arguments to initialize and configure the sub-content processor. -The sub-content processor is a regular filter parser which implements the [ISubContentParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentParser.yml) interface. Two of its requirements are to be able to handle streams and document fragments. The parser receives the stream containing the sub-content when the File Type Support Framework calls the [InitializeSubContentParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentParser_InitializeSubContentParser_System_IO_Stream_) method. The parser must simply use this stream to parse the content from. Everything else is set up in the same way as for file-based parsing. +The sub-content processor is a regular filter parser implementing the [ISubContentParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentParser.yml) interface. It must handle streams and document fragments. When the framework calls [InitializeSubContentParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentParser_InitializeSubContentParser_System_IO_Stream_), it passes a stream containing the sub-content. The parser uses this stream to parse the content. The rest of the setup is identical to file-based parsing. -For target regeneration, the framework makes calls to a sub-content writer which builds up the sub-content during these calls. The sub-content writer must implement the [ISubContentWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml) interface. The framework initially calls the [InitializeSubContentWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentWriter_InitializeSubContentWriter_System_IO_Stream_) method in order to pass in the original sub-content, in case the writer needs this data to reconstruct the generated content. Once all of the sub-content has been built up, the framework calls the [GetSubContentStream](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentWriter_GetSubContentStream) method in order to retrieve the sub-content stream from the writer. In order for the framework to pass the sub-content back to the main writer for insertion into its output stream, the main writer must implement the [ISubContentAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentAware.yml) interface. This allows the framework to call the [AddSubContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentAware_AddSubContent_System_IO_Stream_) method and pass the sub-content to the main writer. +For target regeneration, the framework uses a sub-content writer implementing the [ISubContentWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml) interface. The framework calls [InitializeSubContentWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentWriter_InitializeSubContentWriter_System_IO_Stream_) to pass the original sub-content. This allows the writer to access the original data when reconstructing content. After all sub-content is built, the framework calls [GetSubContentStream](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentWriter_GetSubContentStream) to retrieve the rebuilt sub-content stream. -In order for the framework to be aware of a sub-content processor, it must implement a component builder which specifies which parser and writer to use for the processing of sub-content. The component builder must implement two interfaces, namely, [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) and [ISubContentComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml). The component builder must implement [BuildSubContentExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISubContentComponentBuilder_BuildSubContentExtractor_System_String_) and [BuildSubContentGenerator](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISubContentComponentBuilder_BuildSubContentGenerator_System_String_). These methods are similar to the regular [BuildFileExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileTypeComponentBuilder_BuildFileExtractor_System_String_) and [BuildFileGenerator](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileTypeComponentBuilder_BuildFileGenerator_System_String_) methods, but instead, allow the component builder to specify a specific parser and writer along with additional processors for the sub-content processing. The method [BuildFileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileTypeComponentBuilder_BuildFileTypeInformation_System_String_) should also be implemented, however, all other methods may return null. A unique File Type Identifier should also be used for each processor. Please note that File Sniffers are not used by sub-content processors. +The main writer must implement [ISubContentAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentAware.yml) to receive sub-content from the framework. The framework calls [AddSubContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentAware_AddSubContent_System_IO_Stream_) to pass the sub-content to the main writer for insertion into its output stream. -The same settings pages may be used for sub-content processor where this makes sense. Usually sub-content processors use a sub-set of the main filter's setting pages with some instances of customized settings pages required. +To use a sub-content processor, the framework must know about it through a component builder. The component builder implements two interfaces: [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) and [ISubContentComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml). It must implement these methods: -In order to display the sub-content FileTypeConfiguration Ids in your UI, you must pass in the list of UIs from the settings page to the UI control. You can then populate a dropdown with the Ids and allow the user to select which processor they will use to handle the sub-content from the main filter. Here you can see how the Ids are obtained via [SubContentFileTypeConfigurationIds](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeConfigurationAware.yml#Sdl_FileTypeSupport_Framework_Core_Settings_IFileTypeConfigurationAware_SubContentFileTypeConfigurationIds). The selected Id should be stored in a settings object which can be accessed by the main parser and passed along in the [ProcessSubContentEventArgs](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ProcessSubContentEventArgs.yml) via the [ProcessSubContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentPublisher_ProcessSubContent) event call. +- [BuildSubContentExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISubContentComponentBuilder_BuildSubContentExtractor_System_String_) — Specifies the parser to use +- [BuildSubContentGenerator](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISubContentComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISubContentComponentBuilder_BuildSubContentGenerator_System_String_) — Specifies the writer to use -Embedded content (or sub-content) is processed by the framework in a sequential manner. First, the main filter processes its content and if it detects any sub-content then raises an event passing in the sub-content. The sub-content parser is then called and consumes all of the sub-content. When this is done, the framework continues with the main parser again. This flow is shown as follows: +These methods differ from the regular [BuildFileExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileTypeComponentBuilder_BuildFileExtractor_System_String_) and [BuildFileGenerator](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileTypeComponentBuilder_BuildFileGenerator_System_String_) methods because they specify both a parser and writer plus additional processors for sub-content. You must also implement [BuildFileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_IFileTypeComponentBuilder_BuildFileTypeInformation_System_String_). All other methods can return null. Use a unique File Type Identifier for each processor. Note: File Sniffers are not used by sub-content processors. + +You can reuse settings pages from the main filter in sub-content processors when appropriate. Sub-content processors typically use a subset of the main filter's settings pages, though custom settings pages may be required for some processors. + +To display sub-content FileTypeConfiguration IDs in your UI, pass the list from the settings page to your UI control. Populate a dropdown with the IDs to let users select which processor handles the sub-content. Access the IDs via [SubContentFileTypeConfigurationIds](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Core.Settings.IFileTypeConfigurationAware.yml#Sdl_FileTypeSupport_Framework_Core_Settings_IFileTypeConfigurationAware_SubContentFileTypeConfigurationIds). Store the selected ID in a settings object accessible by the main parser. Pass the ID in [ProcessSubContentEventArgs](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ProcessSubContentEventArgs.yml) when raising the [ProcessSubContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml#Sdl_FileTypeSupport_Framework_NativeApi_ISubContentPublisher_ProcessSubContent) event. + +The framework processes embedded content (or sub-content) sequentially. The main filter processes its content. When it detects sub-content, it raises an event passing the sub-content to the framework. The sub-content parser consumes all the sub-content. When complete, the framework continues processing the main content. This flow is shown as follows: ![EmbeddedContentFlow](images/EmbeddedContentFlow.jpg) -This is saved in the SDLXLIFF file as individual file sections as shown above. In Var:ProductName, this is presented as: +This is saved in the SDLXLIFF file as individual file sections. In Var:ProductName, it appears as: ![SEEC](images/SEEC.jpg) diff --git a/apiconcepts/filetypesupport/tag_display_modes.md b/apiconcepts/filetypesupport/tag_display_modes.md index bd869ec097..ad17da5b51 100644 --- a/apiconcepts/filetypesupport/tag_display_modes.md +++ b/apiconcepts/filetypesupport/tag_display_modes.md @@ -1,18 +1,23 @@ -Tag display modes -===== -Tags that occur inside segments are called inline tags. These tags can be placeholders that represent elements such as footnote references, index markers, etc. Tags can also be used to set the character formatting of a particular string, e.g. bold, underline, etc. In this case a tag par (i.e. an opening and a closing tag) are used to enclose the string that has bold, underline, etc. formatting. +# Tag display modes - Var:ProductName offers a 'clutter-free' editing environment. This means that as a general rule, users should only see a minimum amount of inline tags. You can design a file type plug-in in such a way that inline tags are not shown by default. For example, you may decide that the inline tags that define bold character formatting in your particular document format should not be shown by default. If possible, your file type plug-in should be designed to show the actual display formatting, which is more user-friendly that displaying the tags. If required, users can still choose to show the (hidden) inline tags at runtime e.g. by clicking a toolbar button. +Tags that appear inside segments are called inline tags. Inline tags can act as placeholders for elements such as footnote references and index markers. They can also apply character formatting such as bold and underline. In that case, a tag pair (an opening and a closing tag) encloses the formatted text. -As a general rule, tags that define character formatting should not be displayed, while tags that act as placeholders for e.g. hyperlinks, footnote references, etc. should be shown to the user (i.e. not set to hidden). +`Var:ProductName` provides a clutter-free editing environment. Users should see only a minimal number of inline tags. Design your file type plug-in so that inline tags are hidden by default when possible. For example, you can hide tags that define bold formatting in your document format. When possible, show the actual display formatting instead of tags because this is more user-friendly. If users need to view hidden inline tags, they can show them at runtime, for example by clicking a toolbar button. -When inline tags are shown, they have four possible display states that the user can choose from: +As a general rule, hide tags that define character formatting. Show tags that act as placeholders for items such as hyperlinks and footnote references. -* No tag text: only a placeholder symbol is displayed -* Partial tag text (default): the name of the tag is shown, e.g. *footnotereference*, which helps the user ascertain what the tag actually represents -* Full tag text: shows the name of the tag and any attributes, e.g. ** -* Tag id: in an intermediary (SDLXliff) file each tag has a unique id, starting with 1. If the user chooses this option, the tag ids are displayed (i.e. from 1 to n). -Example of an inline tag, which is a placeholder for a footnote reference. The tags that define character formatting are hidden, only the actual formatting is shown. The **footnotereference** tag is shown in the (default) partial tag text display mode. +## Display states for visible inline tags + +When inline tags are visible, users can choose from four display states: + +* **No tag text**: only a placeholder symbol is displayed. +* **Partial tag text** (default): the tag name is shown, for example *footnotereference*. +* **Full tag text**: the tag name and attributes are shown, for example **. +* **Tag ID**: in an intermediary (SDLXLIFF) file, each tag has a unique ID starting with 1, and the displayed value is the tag ID (from 1 to n). + +## Examples + +This example shows an inline tag that acts as a placeholder for a footnote reference. The tags that define character formatting are hidden, so only the actual formatting is shown. The **footnotereference** tag is shown in the default partial tag text display mode. @@ -21,11 +26,11 @@ This is what the inline tag looks like when shown with no tag text: -This is what the inline tag looks like when the full tag text (i.e. including attributes) is shown: +This is what the inline tag looks like when the full tag text (including attributes) is shown: -The tag id (*ph* stands for placeholder): +The tag ID (*ph* stands for placeholder): @@ -34,14 +39,9 @@ The same segment with character formatting tag pairs displayed: -See Also ------------ -[Processing Inline Formatting](processing_inline_formatting.md) - -[Processing Inline Tags](processing_inline_tags.md) - -[Applying Character Formatting](applying_character_formatting.md) - -[Processing Placeholder Tags](processing_placeholder_tags.md) - -[Handling Tags During Segmentation](handling_tags_during_segmentation.md) +## See also +- [Processing Inline Formatting](processing_inline_formatting.md) +- [Processing Inline Tags](processing_inline_tags.md) +- [Applying Character Formatting](applying_character_formatting.md) +- [Processing Placeholder Tags](processing_placeholder_tags.md) +- [Handling Tags During Segmentation](handling_tags_during_segmentation.md) diff --git a/apiconcepts/filetypesupport/text_formatting.md b/apiconcepts/filetypesupport/text_formatting.md index 15c418d1ef..11f4bf82e6 100644 --- a/apiconcepts/filetypesupport/text_formatting.md +++ b/apiconcepts/filetypesupport/text_formatting.md @@ -1,19 +1,18 @@ -Text Formatting -== +# Text Formatting -Complex documents often contain formatting and various styles. For example, most editors will support character formats such as **Bold**, *Italic* and Underline. +Complex documents often contain formatting and styles. For example, most editors support character formats such as **bold**, *italic*, and underline. -The purpose of semi-WYSIWYG formatting support is to allow for any framework editor (i.e. an editor built on top of the framework) to display some level of character formatting information based on common formatting types supported by the framework. Thus, the formatting supported by a specific external editor such as Microsoft Word will be converted by a native processor object (at parseing time) into the framework's semi-WYSIWYG formatting objects. These semi-WYSIWYG formatting objects of the framework can be persisted to a bilingual file format, as indeed they are, for the framework XLIFF file format and read back in by the framework when opening such a document. +Semi-WYSIWYG formatting support allows a framework-based editor to display common character formatting information. During parsing, a native processor converts formatting from an external editor such as Microsoft Word into the framework's semi-WYSIWYG formatting objects. The framework can persist these objects in a bilingual file format, including its XLIFF-based format, and read them back when it opens the document. -To apply character formatting, the [Sdl.FileTypeSupport.Framework.Formatting](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Formatting.yml) class is used. This class contains basic formatting properties which can be used in native or bilingual filters. +To apply character formatting, use the [Sdl.FileTypeSupport.Framework.Formatting](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Formatting.yml) class. This class provides the basic formatting properties that native and bilingual filters use. -Formatting properties should be always applied to [IStartTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IStartTagProperties.yml) and you can assign multiple [IFormattingItem](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Formatting.IFormattingItem.yml) items to one ```Formatting``` property. The text will receive all the formatting that is defined in the opening tag. +Apply formatting properties to [IStartTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IStartTagProperties.yml). You can assign multiple [IFormattingItem](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.Formatting.IFormattingItem.yml) objects to a single `Formatting` property. The text then receives all formatting defined in the opening tag. -[IStartTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IStartTagProperties.yml) and [IEndTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IEndTagProperties.yml) have [CanHide](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractInlineTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractInlineTagProperties_CanHide) properties that allows user to hide tags. In order not to have a tag displayed in the editor, set the CanHide property to True. Of course, the semiy-WYSIWYG formatting itself will still be visible. Below you see an example of how hidding tags makes the view for the translator simpler and more readable. +[IStartTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IStartTagProperties.yml) and [IEndTagProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IEndTagProperties.yml) include a [CanHide](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractInlineTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractInlineTagProperties_CanHide) property that lets users hide tags. To hide a tag in the editor, set `CanHide` to `true`. The semi-WYSIWYG formatting remains visible. This makes the translator's view simpler and easier to read. ![HiddenTags](images/HiddenTags.jpg) -For tags that are meant to apply only character formatting, this property should be always set to True. +For tags that apply only character formatting, set this property to `true`. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/the_file_context.md b/apiconcepts/filetypesupport/the_file_context.md index 33eedba77e..9d16bb45af 100644 --- a/apiconcepts/filetypesupport/the_file_context.md +++ b/apiconcepts/filetypesupport/the_file_context.md @@ -1,12 +1,12 @@ -The File Context -== +# The File Context -Translatable text can occur in one or more contexts. Examples of contexts are file names, URLs, domains, resource types, layout properties (e.g. heading, title, table cell, etc.), and potentially many more. Obviously, contexts can contain other contexts, and they can overlap with other contexts. +Translatable text can appear in one or more contexts. Examples include file names, URLs, domains, resource types, and layout properties such as headings, titles, and table cells. Contexts can contain other contexts, and they can overlap. -Native File Processing API Representation --- +## Native File Processing API representation -During native content processing contexts are created by the filter through [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_). [IContextProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextProperties.yml), the input parameter type of [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_), wraps an [IContextInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml) array. [IContextInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml) has following properties: +During native content processing, the filter creates contexts through [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_). The [IContextProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextProperties.yml) parameter wraps an array of [IContextInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml) objects. + +`IContextInfo` exposes the following properties: * [ContextType](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextInfo_ContextType) * [DefaultFormatting](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextInfo_DefaultFormatting) @@ -16,25 +16,21 @@ During native content processing contexts are created by the filter through [Cha * [DisplayName](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextInfo_DisplayName) * [Purpose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IContextInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_IContextInfo_Purpose) -Every call to [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_) closes all open contexts and opens all contexts specified in the call parameters. - -Conversion from Native to Bilingual --- - -Contexts must be identified, created, and maintained by filters. To pass them into the framework the filter must use the [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_) method of the [IAbstractNativeContentHandler](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml) interface. There is no default context. Using contects is not mandatory, but it is recommended to improve translation and match quality, as translators can easily identify a translatable string as e.g. a headline, footnote, etc., which may be important information for the translation process. +Every call to [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_) closes the currently open contexts and opens the contexts specified in the call. -Conversion from Bilingual to Native --- +## Conversion from native to bilingual -Contexts are not part of the native format and will therefore not show up in translated files. +Filters must identify, create, and maintain contexts. To pass them into the framework, use the [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_) method on [IAbstractNativeContentHandler](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml). The framework does not provide a default context. -See Also --- +Contexts are optional, but they improve translation and match quality. For example, they help translators identify whether a string is a heading, footnote, or another content type that affects translation. +## Conversion from bilingual to native +Contexts are not part of the native file format, so they do not appear in translated output files. -[Adding Context Information](adding_context_information.md) +## See also +- [Adding Context Information](adding_context_information.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/the_file_parser.md b/apiconcepts/filetypesupport/the_file_parser.md index f786c1ab65..484793c810 100644 --- a/apiconcepts/filetypesupport/the_file_parser.md +++ b/apiconcepts/filetypesupport/the_file_parser.md @@ -1,9 +1,8 @@ -The File Parser -== +# The File Parser -When writing filters that use the Native API (for monolingual file formats) you must derive your parser class from the interfaces [INativeFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileTypeComponent.yml) and [INativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileParser.yml). These interfaces provide a way of connecting to the File Type Support Framework and allow the class to initialize the parser with the necessary objects it requires to interact with the File Type Support Framework. A parser will also normally derive from the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interface, which provides the parser with additional information such as the original file path name, source language and encoding. These interface class methods are called during key phases of the parsing process to enable your filter to manage its initialization, flow-control and clean-up. +When you build a filter that uses the Native API for monolingual file formats, your parser must connect to the File Type Support Framework through [INativeFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileTypeComponent.yml) and [INativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileParser.yml). In most cases, the parser also implements [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml), which provides information such as the original file path, source language, and encoding. The framework calls these members at key stages of parsing so that your filter can initialize, control the parsing flow, and clean up correctly. -However, the simplest way to implement a native parser is to merely it derive from the [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml) class and the ```INativeContentCycleAware``` interface and then use the helper functions of the ```AbstractNativeFileParser``` class. +The simplest way to implement a native parser is to derive from [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml) and implement `INativeContentCycleAware`. You can then use the helper methods that `AbstractNativeFileParser` provides. # [C#](#tab/tabid-1) ```cs @@ -14,32 +13,40 @@ public class SimpleTextParser : AbstractNativeFileParser, INativeContentCycleAwa ``` *** -Deriving from the ```AbstractNativeFileParser``` base class provides an implementation of the ```INativeFilterComponent``` and ```INativeFileParser``` interfaces, leaving only the ```INativeContentCycleAware``` and ```ISettingsAware``` interfaces to be implemented by the derived class. If this class is used as a base class, then in its implementation of ```INativeFileParser``` it provides some overridable methods than can be used to simplify the implementation of a native parser class. These overridable methods are as follows: +## Using `AbstractNativeFileParser` -* [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing): This method is called **before** any parsing commences and before the ```DuringParsing()``` method is called. Any initialization of variables, opening of a file, etc. can be done in the overridden implementation of this method after calling the base class implementation. -* [DuringParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_DuringParsing): This method is called after the initial call to the ```BeforeParsing()``` method and subsequently for each chunk of processing that needs to be done for the file to be extracted. The implementation should return True, if there is more processing to be done and False after the file processing has been completed. -* [AfterParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_AfterParsing): This method is called **after** ```DuringParsing() ```returns False to indicate that the file processing is complete. This method can be overridden to implement closing of the file or any tidying up operations. -* [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_): This method can be used to inform the framework - and hence the user - of the file parsing progress. It takes a byte parameter with values between 0 and 100 as a percentage of file processing progress. -* [OutputText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OutputText_System_String_) method: The ```OutputText()``` method can be used to output translatable text to the File Type Support Framework API. This process will be explained in more detail in the section: [Implement the File Parser](implementing_the_file_parser.md). -* [Dispose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_Dispose) method: This method is implemented in ```AbstractNativeFileParser``` and can be overridden by subclasses. This method is explicitly called after an unhandled exception is thrown in the Filter Framework. This is the last chance for the filter to release acquired resources (managed and unmanged). This can happen when: - Acquire resources in ```StartOfInput()``` and release them in ```EndOfInput()``` - Acquire resources in BeforeParsing() and release them in ```AfterParsing()``` - Acquire resources in ```SetFileProperties()``` and release them in ```FileComplete()``` - or other similar situations. +The `AbstractNativeFileParser` base class already implements `INativeFilterComponent` and `INativeFileParser`. This leaves your derived class to implement `INativeContentCycleAware` and, if needed, `ISettingsAware`. It also exposes overridable methods that simplify the implementation of a native parser. -You may have noticed that we have not yet explained how you access essential information such as the actual name of the file to be processed. For this, we refer you back to the ```INativeContentCycleAware``` interface. This interface contains the method ```SetFileProperties()```. Its standard implementation is to save its parameter (**IFileProperties** properties) to a class variable. Probably the most commonly used member is FileConversionProperties, which in turn implements the following: +* [BeforeParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_BeforeParsing): Called **before** parsing begins and before `DuringParsing()` is called. Override this method to initialize variables, open files, or perform similar setup tasks after you call the base implementation. +* [DuringParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_DuringParsing): Called after the initial `BeforeParsing()` call and then repeatedly for each chunk of work that the parser must process. Return `true` while parsing should continue and `false` when parsing is complete. +* [AfterParsing](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_AfterParsing): Called **after** `DuringParsing()` returns `false`. Override this method to close files or perform other cleanup tasks. +* [OnProgress](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OnProgress_System_Byte_): Reports file parsing progress to the framework and the user. It takes a byte value between `0` and `100`. +* [OutputText](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_OutputText_System_String_): Sends translatable text to the File Type Support Framework API. For more information, see [Implement the File Parser](implementing_the_file_parser.md). +* [Dispose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileParser_Dispose): Can be overridden to release resources if the Filter Framework throws an unhandled exception. This is the last opportunity to release managed or unmanaged resources. Typical patterns include acquiring resources in `StartOfInput()` and releasing them in `EndOfInput()`, or acquiring resources in `BeforeParsing()` and releasing them in `AfterParsing()`. -* [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath): This property contains the full path name to the monolingual source file that the content originates from. -* [OriginalEncoding](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalEncoding): This property contains the original encoding (if known) of the monolingual file that the content originates from. -* [SourceLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_SourceLanguage): This property contains the original source language of the monolingual file’s translatable content. -* [FileSnifferInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_FileSnifferInfo): This property can contain information generated by a [file sniffer](the_file_sniffer.md) component. The most relevant item provided by the ```FileSnifferInfo``` interface will probably be the ```DetectedEncoding``` property. -* [DependencyFiles](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_DependencyFiles): This property is a list of names of dependency files that are used or created while parsing. This may even include the original source document. A copy of these files is then created and encoded as part of the bilingual intermediate file format (SDLXliff). All files are then decoded to temporary file names and made available to the Native API writer during the native file genration phase. The set of dependency files can change while parsing, but should not change after the ```INativeContentCycleAware.EndOfInput()``` call has been invoked. Any dependency files that are reported by a parser or filter component while parsing a native file will be decoded to a temporary file and passed through this property when generating the native file. In future releases of the File Type Support Framework API it will also be possible to add a link to dependency file instead of embedding it. The documentation for this ```DependencyFiles``` property will be updated as soon as this functionality becomes available. +## Accessing file information -The ```INativeContentCycleAware``` interface contains two further methods that need to be implemented in any parser class, which are outlined below. However, if you are using the flow control methods of the ```AbstractNativeFileParser``` base class, your implementation methods may not require any code content. +To access essential information such as the name of the file being processed, use `INativeContentCycleAware`. This interface includes `SetFileProperties()`. A typical implementation stores the `IFileProperties` parameter in a class field. One of the most useful members is `FileConversionProperties`, which exposes the following properties: -* **SetFileProperties** method: Returns a ```IPersistentFileConversionProperties``` object. -* [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput): This method is called by the framework after component initialisation (i.e. after ```SetFileProperties()```, but before any content is parsed and passed to any of the filter components. -* [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput): This method is called by the framework after the finishing processing of the native (monolingual) content. +* [OriginalFilePath](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalFilePath): The full path to the monolingual source file. +* [OriginalEncoding](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_OriginalEncoding): The original encoding of the source file, if known. +* [SourceLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_SourceLanguage): The original source language of the file's translatable content. +* [FileSnifferInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_FileSnifferInfo): Information produced by a [file sniffer](the_file_sniffer.md) component. In many cases, the most useful value is `DetectedEncoding`. +* [DependencyFiles](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IPersistentFileConversionProperties_DependencyFiles): The list of dependency files that the parser uses or creates during parsing. This list can include the original source document. The framework stores these files in the intermediate bilingual format, then decodes them to temporary file names and makes them available to the Native API writer during native file generation. The set of dependency files can change while parsing is in progress, but it should not change after `INativeContentCycleAware.EndOfInput()` is called. -The ```ISettingsAware``` interface contains one method that needs to be implemented in any parser class, which requires access to any settings the parser may need. This is shown below: +## Implementing `INativeContentCycleAware` -* [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) method: Passes in an ```ISettingsBundle``` object and a configurationId FileTypeConfigurationId. These can be used to populate the required settings object used by the parser: +`INativeContentCycleAware` also defines two additional methods that your parser must implement. If you use the flow-control methods in `AbstractNativeFileParser`, these implementations may not need much code. + +* `SetFileProperties()`: Stores the file properties that the framework passes to the parser. +* [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput): Called after component initialization, including `SetFileProperties()`, but before the framework parses and passes any content to filter components. +* [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput): Called after the framework finishes processing the native content. + +## Implementing `ISettingsAware` + +If your parser needs access to user or file type settings, implement `ISettingsAware`. + +* [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_): Passes an `ISettingsBundle` object and a `configurationId` (`FileTypeConfigurationId`). Use these values to populate the settings object that the parser requires. # [C#](#tab/tabid-2) ```cs diff --git a/apiconcepts/filetypesupport/the_file_sniffer.md b/apiconcepts/filetypesupport/the_file_sniffer.md index 31abe0f9c8..9acd69f40f 100644 --- a/apiconcepts/filetypesupport/the_file_sniffer.md +++ b/apiconcepts/filetypesupport/the_file_sniffer.md @@ -1,28 +1,37 @@ -The File Sniffer -== +# The File Sniffer -File sniffers are small classes that are implemented to quickly determine whether a given file is supported by the parser that they are acting for. When a file sniffer is specified in the corresponding File Type Component Builder, it will be invoked by the framework **before** the actual file parsing begins. When the file sniffer determines that a given file cannot be processed by the filter, it will, for example, throw a corresponding message for the user, and the file will not be sent to the file parser, which will save processing time. +A file sniffer is a small class that quickly determines whether a parser supports a file. If you specify a file sniffer in the corresponding File Type Component Builder, the framework calls it **before** parsing starts. If the sniffer determines that the filter cannot process the file, the framework can report that result to the user and skip the parser. This reduces unnecessary processing. -Usually a sniffer examines the beginning of a document or the document header in order to determine whether the given file is likely to be supported by the filter or not. This may be done, for example, by looking for certain XML element names or by examining the first few bytes of a file. If a whole file needs woud need to be read and processed to determine if the doucment is valid or not, then the file sniffer's value is significantly diminished, because it will add more processing time to the filter, and an exception could be raised in the parser anyway if the source document was found to be invalid. However, there is some merit in having XML documents being validated against a schema within a file sniffer especially if this extra validation step can be made configurable. +## How a file sniffer works -The file sniffer class needs to contain one member, i.e. the ```Sniff()``` method, which takes three parameters: a file path, a language and a suggested codepage. The given file is checked to see if it is a supported file type. The provided language and codepage may be used to help determines if this is the case. +A file sniffer usually examines the start of a document or its header to determine whether the filter is likely to support the file. For example, it can look for specific XML element names or inspect the first few bytes of a file. -The ```Sniff()``` method returns a [SniffInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml) object, which has four properties: +If the sniffer must read and process the entire file to determine whether the document is valid, it provides less value. In that case, it adds processing time and the parser could raise an exception anyway when it detects an invalid source document. XML schema validation can still be useful in a file sniffer, especially when you make that extra validation step configurable. + +## The `Sniff()` method + +The file sniffer class must implement one member: the `Sniff()` method. This method takes three parameters: a file path, a language, and a suggested code page. It checks whether the file is a supported file type. The provided language and code page can help make that determination. + +The `Sniff()` method returns a [SniffInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml) object with the following four properties: * [IsSupported](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml) to indicate if a given document is supported. * [DetectedEncoding](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_DetectedEncoding) to indicate the encoding of a given document. * [DetectedSourceLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_DetectedSourceLanguage) to indicate the source language of a given document. -* [DetectedTargetLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_DetectedTargetLanguage) to indicate the target language of given document. +* [DetectedTargetLanguage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.SniffInfo.yml#Sdl_FileTypeSupport_Framework_NativeApi_SniffInfo_DetectedTargetLanguage) to indicate the target language of the given document. + +## Passing metadata + +If necessary, you can store additional information for later use in the parser or writer component. For example, you can store the line break type. Use [SetMetaData](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml#Sdl_FileTypeSupport_Framework_NativeApi_IMetaDataContainer_SetMetaData_System_String_System_String_) and [GetMetaData](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml#Sdl_FileTypeSupport_Framework_NativeApi_IMetaDataContainer_GetMetaData_System_String_) to save and load metadata in a `SniffInfo` object. -If required, you can store extra information for further use in the parser or writer component, for example the type of line break etc., using the [SetMetaData](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml#Sdl_FileTypeSupport_Framework_NativeApi_IMetaDataContainer_SetMetaData_System_String_System_String_) and [GetMetaData](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IMetaDataContainer.yml#Sdl_FileTypeSupport_Framework_NativeApi_IMetaDataContainer_GetMetaData_System_String_) methods to store/load any additional information in/from a ```SniffInfo``` object. +These custom values are then available through an [IPersistentFileConversionProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml) object. -These custom values are then accessible through a [IPersistentFileConversionProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IPersistentFileConversionProperties.yml) object. +## Reading settings -Any settings that may be required by the file sniffer are passed in via an ISettingsGroup. This allows the file sniffer to set up any required settings in a manner like that shown below: +Any settings that the file sniffer requires are passed in through an `ISettingsGroup`. This allows the file sniffer to initialize its settings, as shown in the following example: # [C#](#tab/tabid-1) ```cs - private void OverrideSettings(ISettingsGroup settingsGroup) +private void OverrideSettings(ISettingsGroup settingsGroup) { if (settingsGroup == null) { @@ -34,7 +43,7 @@ Any settings that may be required by the file sniffer are passed in via an ISett ``` *** -This can be called from within the ```Sniff()``` method body and will populate any required settings. +Call this method from within `Sniff()` to populate the required settings. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/the_file_type_plug_in_life_cycle.md b/apiconcepts/filetypesupport/the_file_type_plug_in_life_cycle.md index 0e6980ad29..680d6a63e9 100644 --- a/apiconcepts/filetypesupport/the_file_type_plug_in_life_cycle.md +++ b/apiconcepts/filetypesupport/the_file_type_plug_in_life_cycle.md @@ -1,44 +1,49 @@ -The File Type Plug-in Lifecycle -== +# The File Type Plug-in lifecycle -This section describes the lifecycle and in particular the initialization process for components in the File Type Support Framework. +This page describes the lifecycle of File Type Support Framework components, with a focus on initialization. -During its lifecycle a filter component may go through the following steps: +During its lifecycle, a filter component can go through the following steps: -1. The component is instantiated. -The components are explicitly created and initialized using PocoFilterManger (see [Initializing the File Type Manager](initializing_the_file_type_manager.md)). +1. **Instantiate the component.** + `PocoFilterManager` explicitly creates and initializes the components. For more information, see [Initializing the File Type Manager](initializing_the_file_type_manager.md). -2. If the component implements the `IComponentsAware` interface, the `SetComponents()` method will be called before the component is used. Every time the set of components change, this component will be included in the changes. -This allows the component to retrieve information on other components with which it is being used. This may be useful e.g. to determine if it should synchronize its settings with any other known components. +2. **Set related components.** + If the component implements `IComponentsAware`, the framework calls `SetComponents()` before the component is used. The framework also calls this method whenever the component set changes. This lets the component inspect related components and, for example, decide whether it should synchronize settings with them. -3. If the component implements the `INativeFilterComponent` interface the `PropertiesFactory` and `MessageReporter` properties will be set. Components should only create property objects through the property factory. This ensures that all filter components that are used together use the same type of property objects. +3. **Set native component services.** + If the component implements `INativeFilterComponent`, the framework sets the `PropertiesFactory` and `MessageReporter` properties. Components should create property objects only through the property factory. This ensures that cooperating filter components use the same property object types. - Normally the File Type Support Framework provides a default factory. However, it is possible for the parser to set the factory that should be used by all the components. If a native parser exposes an existing properties factory through the `INativeFilterComponent` interface at initialization time, that factory will be used. + The File Type Support Framework normally provides a default factory. However, a parser can provide the factory that all components should use. If a native parser exposes an existing properties factory through `INativeFilterComponent` during initialization, the framework uses that factory. -4. If the component implements the `IBilingualFilterComponent` interface, the `ItemsFactory` property will be set. Components should only create bilingual content model items through this factory. +4. **Set bilingual item services.** + If the component implements `IBilingualFilterComponent`, the framework sets the `ItemsFactory` property. Components should create bilingual content model items only through this factory. - Normally the File Type Support Framework provides a default factory. However, it is possible for the parser to set the factory that should be used by all the components. If a bilingual parser implements the `IBilingualFilterComponent` and returns a non-null value from the `ItemsFactory` property, it is that factory that will be used. + The File Type Support Framework normally provides a default factory. However, a parser can provide the factory that all components should use. If a bilingual parser implements `IBilingualFilterComponent` and returns a non-null value from `ItemsFactory`, the framework uses that factory. -5. If the component implements the `INativeContentCycleAware` interface, the `SetFileProperties()` method will be called. The file conversion properties (a member of the file properties), among other things, contain the name of the native file that is being processed (in the OriginalFilePath property). Native file parsers must implement this interface and obtain the name of the file to parse from this property. +5. **Set file properties.** + If the component implements `INativeContentCycleAware`, the framework calls `SetFileProperties()`. The file conversion properties, which are part of the file properties, include the name of the native file being processed in `OriginalFilePath`. Native file parsers must implement this interface and read the file name from that property. - The file conversion properties can be changed by the filter components at any time. Since the same object is referenced by all components, changes to the object immediately affect all other components. + Filter components can change the file conversion properties at any time. Because all components reference the same object, any change becomes visible to the other components immediately. - Bilingual processor components normally should not implement this interface. They will obtain the corresponding information (and more) through the `SetFileProperties()` call on the `IBilingualContentProcessor` interface. - For some components this method may be called several times during their lifetime, due to the fact that an XLIFF document may contain content from multiple native files. The method will be invoked before content originating from each native file is processed. + Bilingual processor components should not usually implement this interface. They receive the corresponding information, and more, through the `SetFileProperties()` call on `IBilingualContentProcessor`. - The file conversion properties will be serialized into the bilingual document format and de-serialized and applied applied to filter components as part of the initialization. + Some components may receive this method call several times during their lifetime because an XLIFF document can contain content from multiple native files. The framework invokes the method before it processes content from each native file. - Filter components can store dynamically configured settings and any other type of information in this object. They rely on this information being available the next time the same content is processed. Settings are stored and retrieved as key/value pairs. To avoid conflicts with other components each filter component should use a unique prefix for their settings keys. Built-in framework components use the "SDL:" prefix for all their settings keys. + The framework serializes the file conversion properties into the bilingual document format, then deserializes and reapplies them to filter components during initialization. -6. If a native component implements the `INativeOutputSettingsAware` interface, the `SetOutputProperties()` method is invoked. -This allows components to find out about the purpose of the conversion, whether it will be processing source or target content, what the file path to the output file is, the preferred encoding for the output file, etc. + Filter components can also store dynamic settings and other information in this object. They rely on that information being available the next time the same content is processed. Store settings as key/value pairs. To avoid conflicts, each filter component should use a unique prefix for its setting keys. Built-in framework components use the `SDL:` prefix. -7. If a native filter component implements the INativeContentCycleAware interface, the `StartOfInput()` method will be called immediately before parsing begins. -Bilingual processors receive calls to `Initialize()` and `SetFileProperties`() on the IBilingualContentProcessor interface before content is passed through them. +6. **Set output properties.** + If a native component implements `INativeOutputSettingsAware`, the framework calls `SetOutputProperties()`. This lets the component determine the conversion purpose, whether it will process source or target content, the output file path, the preferred output encoding, and related settings. -8. The components will now be used to process actual content. -9. If a native filter component implements the INativeContentCycleAware interface, the `EndOfInput()` method will be called immediately after the parsing has completed. -Bilingual processor components receive calls to `FileComplete()` and `Complete()` as appropriate. +7. **Start content processing.** + If a native filter component implements `INativeContentCycleAware`, the framework calls `StartOfInput()` immediately before parsing begins. Bilingual processors receive `Initialize()` and `SetFileProperties()` on `IBilingualContentProcessor` before content passes through them. + +8. **Process the content.** + The components now process the actual content. + +9. **Complete content processing.** + If a native filter component implements `INativeContentCycleAware`, the framework calls `EndOfInput()` immediately after parsing completes. Bilingual processor components receive `FileComplete()` and `Complete()` as appropriate. >[!NOTE] diff --git a/apiconcepts/filetypesupport/the_file_writer.md b/apiconcepts/filetypesupport/the_file_writer.md index d386d70d63..f811cb08a5 100644 --- a/apiconcepts/filetypesupport/the_file_writer.md +++ b/apiconcepts/filetypesupport/the_file_writer.md @@ -1,36 +1,50 @@ -The File Writer -== +# The File Writer -The last step in the localization workflow is the generation of the (translated) target file in the original document format. In one of the examples provided in this SDK we need to write all translated segments from a bilingual SDLXliff document to a (native)SubRip file. This task is performed by a Native API Writer. +The final step in the localization workflow is to generate the translated target file in its original document format. For example, an SDK sample writes translated segments from a bilingual SDLXLIFF document to a native SubRip file. A Native API writer performs this task. -When implementing a Native API file writer you must derive your writer class from the interfaces [INativeFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileTypeComponent.yml) and [INativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileWriter.yml). These interfaces provide a way of connecting to the File Type Support Framework and allowing it to initialize the writer with the objects it needs to interact with the File Type Support Framework. A writer will also normally derive from the [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml), [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) and [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml) interfaces, which provide the writer with additional information such as the target file path name, the target language and the preferred encoding of the target file and also allow any required settings to be populated. +## Implementing a Native API writer -However, the simplest way to implement a native writer is to merely derive it from the [AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml) class and the [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml) interfaces, and use the helper functions of the ```AbstractNativeFileWriter``` class. +When you implement a Native API file writer, your class must connect to the File Type Support Framework through [INativeFileTypeComponent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileTypeComponent.yml) and [INativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileWriter.yml). In most cases, the writer also implements [INativeOutputSettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeOutputSettingsAware.yml), [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml), and [ISettingsAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml). These interfaces provide information such as the target file path, target language, preferred encoding, and any required settings. -The ```AbstractNativeFileWriter``` base class provides an implementation of the ```INativeFilterComponent```, ```IAbstractNativeContentHandler``` and ```INativeOutputSettingsAware``` interfaces leaving only the INativeContentCycleAware interface to be implemented by the derived class. If this ```AbstractNativeFileWriter``` class is used as a base class, in its implementations of ```IAbstractNativeContentHandler``` it provides some default (empty) implementations of the interface methods. These public virtual methods can be overwritten in the derived class if an implementation is required for a particular native writer. +The simplest way to implement a native writer is to derive from [AbstractNativeFileWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml) and implement [INativeContentCycleAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml). You can then use the helper methods that `AbstractNativeFileWriter` provides. -You may have noticed that the [IAbstractNativeContentHandler](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml) interface, from which the Native API writer is derived, is the same interface that is used for the ```Output``` property of the [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml) base parser class. The reason for this is that all text, tags and other mark-up items that are written during the parsing phase are re-used when the translated output file is being creating, with the mark-up order and translated text content determined by the translation process. However, the translated document will only contain tags that were created during the parsing phase. The Native API writer can rely on the tag content of each tag to be the same as it was when it was written by the parser with the exception of any manually-added mark-up items in a framework-based editor. If a filter allows for manually created mark-up such as **Bold**, *Italic* or Underline formatting added by the user during translation, then this will be defined in the File Type Component Builder. The only other exception to this is when the parser class has created a tag with localizable content in it. If this is the case, then the [LocalizableContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractTagProperties_LocalizableContent) property of the tag properties must be examined to retrieve the text for the localizable sub-segments. +## Using `AbstractNativeFileWriter` -The ```AbstractNativeFileWriter``` base class provides some default virtual implementations of the ```IAbstractNativeContentHandler``` interface methods that represent tags, text and futher mark-up item in the translated document. Therefore, in your derived Native API writer class, you only need to implement the overridable methods for the text or mark-up that is applicable to your document type. A list of overridable methods is provided below. If however, you are not deriving from ```AbstractNativeFileWriter```, you will need to implement all of the following methods, even if the method content is empty. +The `AbstractNativeFileWriter` base class already implements `INativeFilterComponent`, `IAbstractNativeContentHandler`, and `INativeOutputSettingsAware`. This leaves the derived class to implement `INativeContentCycleAware`. The base class also provides default, empty virtual implementations of `IAbstractNativeContentHandler` members, so you only need to override the methods that matter for your document type. -* [StructureTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_StructureTag_Sdl_FileTypeSupport_Framework_NativeApi_IStructureTagProperties_): This method is called on the Native API writer class when structure tag information is being sent to the writer class. Your implementation (if any) will need to interpret the ```IStructureTagProperties.TagContent``` string that was set by the parser. A simple, text- based file format parsers may only need to write the tag content to the output file. -* [InlineStartTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlineStartTag_Sdl_FileTypeSupport_Framework_NativeApi_IStartTagProperties_): This method is called by the framework when paired start tag information is being sent to the writer. Again, a simple implementation may only need to write the tag content to the output file. -* [InlineEndTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlineEndTag_Sdl_FileTypeSupport_Framework_NativeApi_IEndTagProperties_): This method is called by the framework when the end tag of a pair of tags is being sent to the writer. The framework guarantees that all tag pairs will remain well formed during the translation process. -* [InlinePlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlinePlaceholderTag_Sdl_FileTypeSupport_Framework_NativeApi_IPlaceholderTagProperties_): This method is called by the framework when single placeholder tag information is being sent to the writer. -Text: This method is called by the framework to tell the writer class to write text in human readable form to the output file. This will usually be the translated text, but it could also be the source text when previewing the source document. -* [CustomInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_CustomInfo_Sdl_FileTypeSupport_Framework_NativeApi_ICustomInfoProperties_): This method is for sending temporary custom information that can be used for communication between native content processing components. -* [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_): This method is normally invoked on the Output property of the Native API parser, and is not expected to be used by the writer. However, it still needs to be defined, as it is part of the common ```IAbstractNativeContentHandler``` interface used by both the parser and writer. -* [Dispose](../..//api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_Dispose) method: This method is implemented in ```AbstractNativeFileWriter``` and can be overridden by subclasses. This method is explicitly called after an unhandled exception is thrown in the Filter Framework. This is the last chance for the filter to release acquired resources (managed and unmanged). This can happen when: - Acquire resources in StartOfInput() and release them in EndOfInput() - Acquire resources in BeforeParsing() and release them in AfterParsing() - Acquire resources in SetFileProperties() and release them in FileComplete() - or other similar situations. +The [IAbstractNativeContentHandler](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml) interface is also used by the `Output` property of [AbstractNativeFileParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileParser.yml). This shared interface allows the framework to reuse the text, tags, and other markup produced during parsing when it generates the translated output file. -The ```AbstractNativeFileWriter``` interface contains two further methods that need to be implemented in any writer class. These are outlined below: +In most cases, the writer can assume that tag content matches the content produced by the parser. Two exceptions apply: -* [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_): This method receives a IPersistentFileConversionProperties object. -[StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput): This method is called by the framework after component initialization (i.e. after * SetFileProperties(), but before any content is parsed and passed to any of the filter components. -* [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput): This method is called by the framework after processing of the native (monolingual) content has finished. +* A framework-based editor can add markup manually, such as **bold**, *italic*, or underline, if the File Type Component Builder allows it. +* A parser can create a tag that contains localizable content. In that case, inspect the [LocalizableContent](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractTagProperties.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractTagProperties_LocalizableContent) property to retrieve the localizable subsegment text. -The ```ISettingsAware``` interface contains one method that needs to be implemented in any writer class, which requires access to any settings the writer may need. This is shown below: +## Overridable writer methods -* [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_) method: Passes in an ISettingsBundle object and a configurationId FileTypeConfigurationId. These can be used to populate the required settings object used by the writer, e.g.: +If you derive from `AbstractNativeFileWriter`, override only the methods that your document type requires. If you do not derive from `AbstractNativeFileWriter`, you must implement all of these methods, even when some implementations remain empty. + +* [StructureTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_StructureTag_Sdl_FileTypeSupport_Framework_NativeApi_IStructureTagProperties_): Called when the framework sends structure tag information to the writer. Your implementation interprets `IStructureTagProperties.TagContent`. Simple text-based formats may only need to write that tag content directly to the output file. +* [InlineStartTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlineStartTag_Sdl_FileTypeSupport_Framework_NativeApi_IStartTagProperties_): Called when the framework sends a paired start tag to the writer. A simple implementation may only need to write the tag content to the output file. +* [InlineEndTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlineEndTag_Sdl_FileTypeSupport_Framework_NativeApi_IEndTagProperties_): Called when the framework sends the end tag of a paired tag. The framework guarantees that tag pairs remain well-formed during translation. +* [InlinePlaceholderTag](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_InlinePlaceholderTag_Sdl_FileTypeSupport_Framework_NativeApi_IPlaceholderTagProperties_): Called when the framework sends a standalone placeholder tag to the writer. +* `Text`: Called when the framework sends human-readable text to the writer. This is usually translated text, but it can also be source text when the framework previews the source document. +* [CustomInfo](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_CustomInfo_Sdl_FileTypeSupport_Framework_NativeApi_ICustomInfoProperties_): Sends temporary custom information between native content-processing components. +* [ChangeContext](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IAbstractNativeContentHandler.yml#Sdl_FileTypeSupport_Framework_NativeApi_IAbstractNativeContentHandler_ChangeContext_Sdl_FileTypeSupport_Framework_NativeApi_IContextProperties_): Usually invoked on the parser output rather than on the writer. The writer still defines it because it belongs to the shared `IAbstractNativeContentHandler` interface. +* [Dispose](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.AbstractNativeFileWriter.yml#Sdl_FileTypeSupport_Framework_NativeApi_AbstractNativeFileWriter_Dispose): Can be overridden to release resources if the Filter Framework throws an unhandled exception. This is the last opportunity to release managed or unmanaged resources. + +## Implementing `INativeContentCycleAware` + +Writers that implement `INativeContentCycleAware` must also define the following methods: + +* [SetFileProperties](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_SetFileProperties_Sdl_FileTypeSupport_Framework_BilingualApi_IFileProperties_): Receives an `IPersistentFileConversionProperties` object. +* [StartOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_StartOfInput): Called after component initialization, including `SetFileProperties()`, but before any content is parsed and passed to filter components. +* [EndOfInput](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeContentCycleAware.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeContentCycleAware_EndOfInput): Called after the framework finishes processing the native content. + +## Implementing `ISettingsAware` + +If your writer needs access to settings, implement `ISettingsAware`. + +* [InitializeSettings](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISettingsAware.yml#Sdl_FileTypeSupport_Framework_IntegrationApi_ISettingsAware_InitializeSettings_Sdl_Core_Settings_ISettingsBundle_System_String_): Passes an `ISettingsBundle` object and a `configurationId` (`FileTypeConfigurationId`). Use these values to populate the settings object that the writer requires, for example: # [C#](#tab/tabid-1) ```cs @@ -40,9 +54,7 @@ public void InitializeSettings(Sdl.Core.Settings.ISettingsBundle settingsBundle, _userSettings.PopulateFromSettingsBundle(settingsBundle, configurationId); WriteUtf8Bom = _userSettings.WriteUtf8Bom; } - ``` -*** >[!NOTE] > diff --git a/apiconcepts/filetypesupport/the_filter_component_builder.md b/apiconcepts/filetypesupport/the_filter_component_builder.md index 6696ad718a..19a82664b8 100644 --- a/apiconcepts/filetypesupport/the_filter_component_builder.md +++ b/apiconcepts/filetypesupport/the_filter_component_builder.md @@ -1,15 +1,12 @@ -The Filter Component Builder -== +# The Filter Component Builder -This section contains some information on an example Filter Component Builder code. For a more complete overview, see the File Type Support Framework administration documentation. +This section provides information on an example Filter Component Builder. For more details, see the File Type Support Framework administration documentation. -The default File Type Manager implementation is a simple hardcoded one called PocoFilterManager. This implementation requires a filter to implement the [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml) interface. This includes the implementation of methods to generate objects that implement [IFileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeInformation.yml), [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml), [IFileExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileExtractor.yml), [IFileGenerator](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileGenerator.yml). +The default File Type Manager implementation is PocoFilterManager, a simple hardcoded implementation. To use it, your filter must implement [IFileTypeComponentBuilder](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeComponentBuilder.yml). This interface requires you to implement methods that generate objects implementing [IFileTypeInformation](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileTypeInformation.yml), [INativeFileSniffer](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml), [IFileExtractor](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileExtractor.yml), and [IFileGenerator](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IFileGenerator.yml). -Below you can find an example of a Filter Component Builder class for the "SimpleText" filter . You can take this example and use it as a template, into which you insert your own component information. +The example below shows a Filter Component Builder class for the SimpleText filter. Use this as a template and insert your own component information. -This File Type Component Builder is for a filter that uses the classes ```SimpleTextSniffer```, ```SimpleTextParser``` and ```SimpleTextWriter``` defined in the assembly ```SimpleText```. - -As you may have noticed, the ```SimpleTextFilterComponentBuilder``` implementation of ```IFilterComponentBuilder``` references a lot of types that are defined in the ```Sdl.FileTypeSupport.Framework.Implementation``` assembly. This is where the main part of the File Type Support Framework implementation resides. +This component builder uses the classes `SimpleTextSniffer`, `SimpleTextParser`, and `SimpleTextWriter` defined in the SimpleText assembly. The implementation references many types from the `Sdl.FileTypeSupport.Framework.Implementation` assembly, which contains the core File Type Support Framework implementation. # [C#](#tab/tabid-1) ```cs @@ -30,20 +27,20 @@ namespace Sdk.Snippets.Native public class SimpleTextFilterComponentBuilder : IFileTypeComponentBuilder { /// - /// Gets or sets file type manager + /// Gets or sets the file type manager. /// public IFileTypeManager FileTypeManager { get; set; } /// - /// Gets or sets Filter Definition + /// Gets or sets the file type definition. /// public IFileTypeDefinition FileTypeDefinition { get; set; } /// /// Returns a file type information object. /// - /// The will pass "" as the name for this parameter - /// an SimpleText file type information object + /// The file type definition passes an empty string for this parameter. + /// A SimpleText file type information object. public virtual IFileTypeInformation BuildFileTypeInformation(string name) { var info = this.FileTypeManager.BuildFileTypeInformation(); @@ -69,8 +66,8 @@ namespace Sdk.Snippets.Native /// /// Gets the file sniffer for this component. /// - /// not used here - /// An Simple Text Native Filter Sniffer + /// Not used. + /// A SimpleText file sniffer. public virtual INativeFileSniffer BuildFileSniffer(string name) { return new SimpleTextSniffer(); @@ -79,8 +76,8 @@ namespace Sdk.Snippets.Native /// /// Gets the file extractor for this component. /// - /// not used here - /// a FileExtractor containing an Simple Text Parser + /// Not used. + /// A file extractor containing a SimpleText parser. public virtual IFileExtractor BuildFileExtractor(string name) { var parser = new SimpleTextParser(); @@ -91,18 +88,18 @@ namespace Sdk.Snippets.Native /// /// Gets the file generator for this component. /// - /// not used herer - /// Null if no file generator is defined + /// Not used. + /// A file generator containing a SimpleText writer. public virtual IFileGenerator BuildFileGenerator(string name) { return this.FileTypeManager.BuildFileGenerator(this.FileTypeManager.BuildNativeGenerator(new SimpleTextWriter())); } /// - /// Gets the different sets of previews supported for this component. + /// Gets the preview sets supported for this component. /// - /// not used here - /// not implemented + /// Not used. + /// A preview factory containing preview sets. public virtual IPreviewSetsFactory BuildPreviewSetsFactory(string name) { IPreviewSetsFactory previewFactory = FileTypeManager.BuildPreviewSetsFactory(); @@ -177,15 +174,11 @@ namespace Sdk.Snippets.Native /// /// Creates a new instance of the preview control with the specified name. - /// - /// - /// - /// Should only be called from the main thread, as controls must always be + /// This method must be called from the main thread to ensure controls are /// instantiated on the same thread as the application message pump. - /// - /// - /// not used here - /// not implemented + ///
+ /// Not used. + /// A preview control instance, or null if not implemented. public virtual IAbstractPreviewControl BuildPreviewControl(string name) { if (name == "PreviewControl_InternalStaticPreviewControl") @@ -204,10 +197,10 @@ namespace Sdk.Snippets.Native } /// - /// Gets the QuickTags object for this component. + /// Gets the quick tags factory for this component. /// - /// not used here - /// a Quick tags factory + /// Not used. + /// A quick tags factory. public virtual IQuickTagsFactory BuildQuickTagsFactory(string name) { IQuickTagsFactory quickTags = FileTypeManager.BuildQuickTagsFactory(); @@ -216,22 +209,21 @@ namespace Sdk.Snippets.Native } /// - /// Gets the verifier list of this component. + /// Gets the verifier collection for this component. + /// The verifier collection is an optional component for a file type. /// - /// not used here - /// a verifier collection - /// The verifier list is an optional component for a file type. + /// Not used. + /// A verifier collection, or null if not implemented. public virtual IVerifierCollection BuildVerifierCollection(string name) { return null; } /// - /// Gets a native or bilingual document generator of the type - /// defined for the specified name. + /// Gets a native or bilingual document generator of the type specified by the name parameter. /// - /// Abstract generator name - /// not generator for default preview + /// The generator name. + /// A generator instance, or null if not implemented. public virtual IAbstractGenerator BuildAbstractGenerator(string name) { if (name == "Generator_DefaultPreview") @@ -249,20 +241,20 @@ namespace Sdk.Snippets.Native } /// - /// The the additional generator information for this file type + /// Gets the additional generator information for this file type. /// - /// not used here - /// not implemented + /// Not used. + /// Additional generator information, or null if not applicable. public virtual IAdditionalGeneratorsInfo BuildAdditionalGeneratorsInfo(string name) { return null; } /// - /// Gets the bilingual writer components for this component (if any). + /// Gets the bilingual document generator for this component, if available. /// - /// not used here - /// null if no bilingual generator is defined + /// Not used. + /// A bilingual generator, or null if not implemented. public virtual IBilingualDocumentGenerator BuildBilingualGenerator(string name) { return null; @@ -270,10 +262,10 @@ namespace Sdk.Snippets.Native /// /// Creates a new instance of the preview application with the specified name. - /// Right now only allows to build expternal preview application. + /// Currently only supports building an external preview application. /// - /// Preview application name - /// External preview application + /// The preview application name. + /// An external preview application, or null if not implemented. public virtual IAbstractPreviewApplication BuildPreviewApplication(string name) { if (name == "PreviewApplication_ExternalPreview") @@ -291,8 +283,6 @@ namespace Sdk.Snippets.Native } } ``` -*** - >[!NOTE] > diff --git a/apiconcepts/filetypesupport/the_filter_preview.md b/apiconcepts/filetypesupport/the_filter_preview.md index f33489a94e..20e598f5bc 100644 --- a/apiconcepts/filetypesupport/the_filter_preview.md +++ b/apiconcepts/filetypesupport/the_filter_preview.md @@ -1,36 +1,36 @@ -The Filter Preview -== +# The filter preview -The preview functionality in the Var:ProductName allows you to display the currently opened document (which is available in the bilingual SDLXliff format) in native format. For example, if user has Microsoft Word document opened in Var:ProductName, he/she can use the preview feature to see what the target document will look like when opened in Microsoft Word proper. +Var:ProductName can display the currently opened document in its native format, even though the editor works with the bilingual SDLXliff file. For example, when users open a Microsoft Word document in Var:ProductName, they can use preview to see how the source or target document will appear in Word. -**Var:ProductName offers the following types of preview:** --- -In Var:ProductName two main preview types are available: +## Preview types -* External Studio preview -* Internal Studio preview -Both preview types offer the three following optiosn: +Var:ProductName provides two main preview types: -* Source: the preview displays the source content in its native format -* Target: the preview displays the target content in its native format -* Bilingual: both source and target content is displayed in the native format +- External Studio preview +- Internal Studio preview + +Both preview types support the following modes: + +- **Source**: displays the source content in its native format. +- **Target**: displays the target content in its native format. +- **Bilingual**: displays both source and target content in the native format. >[!NOTE] > ->The bilingual mode may not be practical for all supported file types and in some file filters this mode is not implemented. +> The bilingual mode may not suit every supported file type. Some file filters do not implement it. + + +## External preview -External Preview --- +External preview generates a native-format file that contains the source or target content, depending on the selected preview mode. It then opens that file in the native application or in another configured application. -The external preview is reponsible for generating of native file format. containing the source or the target content (depends on type of the selected preview) and opening this file in the native or other (configurable option) application. +You can configure a different generator for each external preview mode. The file type configuration file (`*.sdlfiletype`) stores all preview settings. For more information, see [Implementing an External File Preview](implementing_an_external_file_preview.md). -For each mode of the external preview we can set different generator which will generate expected format of the native file. All preview configuration settings are save in the file type configuration (*.sdlfiletype) file. For more details about preview configuration see [Implementing an External File Preview](implementing_an_external_file_preview.md) topic. +## Internal preview -Internal preview --- -Internal preview is responsible for generating of the native file in the format which can be displayed inside the control hosted in Var:ProductName. As hosted control, one of predefined controls in ```Sdl.FileTypeSupport.Framework.PreviewControls``` or the custom control which derives from [ISingleFilePreviewControl](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISingleFilePreviewControl.yml) and [IPreviewUpdatedViaRefresh](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IPreviewUpdatedViaRefresh.yml) or [INavigablePreview](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.INavigablePreview.yml) can be used. +Internal preview generates a native-format file that a control hosted inside Var:ProductName can display. You can use one of the predefined controls in `Sdl.FileTypeSupport.Framework.PreviewControls`, or you can provide a custom control that derives from [ISingleFilePreviewControl](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.ISingleFilePreviewControl.yml) together with [IPreviewUpdatedViaRefresh](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.IPreviewUpdatedViaRefresh.yml) or [INavigablePreview](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.IntegrationApi.INavigablePreview.yml). -For more details about the internal preview implementation see [Implement an Internal Preview](internal_preview_introduction.md) chapter. +For more information about internal preview implementation, see [Implement an Internal Preview](internal_preview_introduction.md). >[!NOTE] > diff --git a/apiconcepts/filetypesupport/the_main_parser.md b/apiconcepts/filetypesupport/the_main_parser.md index 0ddbdc639f..fdb55a2e88 100644 --- a/apiconcepts/filetypesupport/the_main_parser.md +++ b/apiconcepts/filetypesupport/the_main_parser.md @@ -1,10 +1,10 @@ -The Main Parser -== -An example of a simplified Main Parser which publishes sub-content. +# The Main Parser + +This example demonstrates a simplified Main Parser that publishes sub-content. >[!NOTE] > ->Usually, you should not add dependency files to the FileProperties unless they are actually used by the sub-content writer - note the implementation of [ISubContentPublisher](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml) +>Add dependency files to the FileProperties only if the sub-content writer actually uses them. Review the [ISubContentPublisher](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentPublisher.yml) implementation for details. # [C#](#tab/tabid-1) ```cs @@ -71,8 +71,7 @@ namespace Sdk.Snippets.Native } } ``` -*** >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +>This content may be out-of-date. Inspect the libraries in the Visual Studio Object Browser to verify the latest information on this topic. diff --git a/apiconcepts/filetypesupport/the_main_writer.md b/apiconcepts/filetypesupport/the_main_writer.md index 91eb3e065d..7eb48a7e6d 100644 --- a/apiconcepts/filetypesupport/the_main_writer.md +++ b/apiconcepts/filetypesupport/the_main_writer.md @@ -1,7 +1,6 @@ -The Main Writer -== +# The Main Writer -An example of a simplified Main Writer which accepts sub-content from the framework - note the implementation of [ISubContentAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentAware.yml) +This example demonstrates a simplified Main Writer that accepts sub-content from the framework. Review the [ISubContentAware](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentAware.yml) implementation for details. # [C#](#tab/tabid-1) ```cs @@ -70,4 +69,4 @@ namespace Sdk.Snippets.Native >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +>This content may be out-of-date. Inspect the libraries in the Visual Studio Object Browser to verify the latest information on this topic. diff --git a/apiconcepts/filetypesupport/the_resources_file.md b/apiconcepts/filetypesupport/the_resources_file.md index 1c12268d2d..377e2b8b30 100644 --- a/apiconcepts/filetypesupport/the_resources_file.md +++ b/apiconcepts/filetypesupport/the_resources_file.md @@ -1,13 +1,12 @@ -The Resources File -== +# The resources file -The project template includes a **PluginResources.resx** resources file, which stores strings and plug-in UI elements (e.g. the plug-in name, the message texts for any problems that the plug-in reports) that are displayed in the user interface of Var:ProductName. +The project template includes a `PluginResources.resx` file. This file stores strings and plug-in UI elements that Var:ProductName displays in the user interface, such as the plug-in name and any problem messages that the plug-in reports. -By default, this resources file only includes the **Plugin_Name** string. In our implementation we need a number of other strings, e.g. to set the plug-in description and the error message(s) that the plug-in should display after verification. The resources table should therefore look as shown below: +By default, this resource file includes only the `Plugin_Name` string. For this implementation, add more strings for the plug-in description and any error messages that verification should display. The resources table should look like the following example: ![resources_identical_check](images/resources_identical_check.jpg) -The ```Sdl.Sdk.FileTypeSupport.Samples.SimpleText``` sample project folder also contains an icon (**icon.ico**) file, which you can add to the resource file of your project. This is the icon that will be displayed next to the plug-in name in the **Options** dialog box. +The `Sdl.Sdk.FileTypeSupport.Samples.SimpleText` sample project folder also contains an `icon.ico` file. Add this file to your project resource file to display the icon next to the plug-in name in the **Options** dialog box. >[!NOTE] > diff --git a/apiconcepts/filetypesupport/the_sub_content_parser.md b/apiconcepts/filetypesupport/the_sub_content_parser.md index a3f46b30ba..aac0133bd1 100644 --- a/apiconcepts/filetypesupport/the_sub_content_parser.md +++ b/apiconcepts/filetypesupport/the_sub_content_parser.md @@ -1,7 +1,6 @@ -The Sub Content Parser -== +# The Sub Content Parser -An example of a sub-content Parser is shown below - note the implementation of [ISubContentParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentParser.yml) +This example demonstrates a sub-content Parser. Review the [ISubContentParser](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentParser.yml) implementation for details. # [C#](#tab/tabid-1) ```cs @@ -17,15 +16,12 @@ namespace Sdk.Snippets.Native { public class SimpleSubContentTextParser : AbstractNativeFileParser, INativeContentCycleAware, ISubContentParser { - #region "global settings" IPersistentFileConversionProperties _fileConversionProperties; StreamReader _reader = null; private Stream _subContentStream; FormattingGroup _fBold; - #endregion - #region "INativeContentCycleAware members" // through the properties object you can retrieve important information // on the native input file such as the original file name and path public void SetFileProperties(IFileProperties properties) @@ -43,11 +39,7 @@ namespace Sdk.Snippets.Native { } - #endregion - #region "members of AbstractNativeFileParser" - - #region "before parsing" protected override void BeforeParsing() { // set progress reporter to the beginning @@ -63,9 +55,7 @@ namespace Sdk.Snippets.Native _reader = new StreamReader(_subContentStream); } } - #endregion - #region "during parsing" protected override bool DuringParsing() { // iterate through all lines in the input file @@ -75,9 +65,7 @@ namespace Sdk.Snippets.Native } return false; } - #endregion - #region "after parsing" protected override void AfterParsing() { //close original file @@ -87,11 +75,7 @@ namespace Sdk.Snippets.Native //set progres report to 100% OnProgress(100); } - #endregion - - #endregion - #region "process line" // determines whether a given line is // translatable or not // if not, a structure tag is output @@ -108,18 +92,14 @@ namespace Sdk.Snippets.Native WriteText(ProcessFormatting(sLine)); } } - #endregion - #region "text" // output translatable text private void WriteText(string TextContent) { ITextProperties textProperties = PropertiesFactory.CreateTextProperties(TextContent); Output.Text(textProperties); } - #endregion - #region "structure" // output non-translatable text as structure tag private void WriteStructureTag(string TagContent) { @@ -127,9 +107,7 @@ namespace Sdk.Snippets.Native structureTagProperties.DisplayText = TagContent; Output.StructureTag(structureTagProperties); } - #endregion - #region "context" // output context information, not required, but useful // information for the translator private void WriteContext(string ContextContent) @@ -143,9 +121,7 @@ namespace Sdk.Snippets.Native contextProperties.Contexts.Add(contextInfo); Output.ChangeContext(contextProperties); } - #endregion - #region "process formatting" // this function uses regular expressions to identify // what is 'normal' translatable content and which strings // need to be marked up as inline tags, e.g. @@ -170,9 +146,7 @@ namespace Sdk.Snippets.Native } return sLine.Substring(LastPosition, sLine.Length - LastPosition); } - #endregion - #region "write inline tag" // this function outputs an opening or a closing tag // and applies bold character formatting to the strings // that the tags enclose @@ -199,7 +173,6 @@ namespace Sdk.Snippets.Native Output.InlineEndTag(endTag); } } - #endregion public void InitializeSubContentParser(Stream subContentStream) { @@ -212,4 +185,4 @@ namespace Sdk.Snippets.Native >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +>This content may be out-of-date. Inspect the libraries in the Visual Studio Object Browser to verify the latest information on this topic. diff --git a/apiconcepts/filetypesupport/the_sub_content_writer.md b/apiconcepts/filetypesupport/the_sub_content_writer.md index ea414d0585..647fd0d16b 100644 --- a/apiconcepts/filetypesupport/the_sub_content_writer.md +++ b/apiconcepts/filetypesupport/the_sub_content_writer.md @@ -1,7 +1,6 @@ -The Sub Content Writer -== +# The Sub Content Writer -An example of a sub-content Writer is shown below - note the implementation of [ISubContentWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml) +This example demonstrates a sub-content Writer. Review the [ISubContentWriter](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.ISubContentWriter.yml) implementation for details. # [C#](#tab/tabid-1) ```cs @@ -59,7 +58,7 @@ namespace Sdk.Snippets.Native public void InitializeSubContentWriter(Stream originalSubContent) { - // We don't make use of the original source content in this writer, so we can ignore this input parameter here. + // This writer ignores the original source content, so we can disregard this input parameter. } } } @@ -68,4 +67,4 @@ namespace Sdk.Snippets.Native >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +>This content may be out-of-date. Inspect the libraries in the Visual Studio Object Browser to verify the latest information on this topic. diff --git a/apiconcepts/filetypesupport/used_terminology.md b/apiconcepts/filetypesupport/used_terminology.md index df476d3c2f..b4ed205fc1 100644 --- a/apiconcepts/filetypesupport/used_terminology.md +++ b/apiconcepts/filetypesupport/used_terminology.md @@ -1,25 +1,25 @@ -Used Terminology -========= +# Used terminology -File Type Support Framework Terminology ------- +## File Type Support Framework terminology -| Term | Explanation | Synonym, Older Term or Related Concept| -| ----------- | ----------- |---------------------------------------| -|File Type Support Framework | Trados File Type Support Framework 2 API | Trados -> Filter Framework 1.0 -| Source | Refers to the source language, i.e. the language the localizable material is translated from | Original| -| Target | Refers to a target language, i.e. one of the languages that is translated into | Translated| -| Native | Content in a single language (source or target), normally before or after it is being localized. | monolingual; original file type| -| Bilingual | Content as it is being processed during localization, normally in source and target language pairs. | TRADOStag, XLIFF, Workbench RTF| -| Text | Localizable text content. | | -| Tag |Content that must not be changed during localization. Tags are protected from accidental modification while editing localizable content in tools such as TagEditor or SDLEdit. | | -| Inline Tag | A tag that appears inside localizable content and that may need to be placed in a different location as part of the localization effort. Examples of elements that are represented as inline tags include links, local formatting overrides, embedded graphics, etc.| Internal Tag, tw4winInternal| -| Structure Tag | A tag that appears outside of the localizable content. These tags typically represent structural information (thus the name) in the document, such as paragraphs, tables, headers, footers, etc.| External Tag, tw4winExternal| -| (Inline) Placeholder Tag | An inline tag that can be treated as a stand-alone element. Examples include index markers, inline graphics, etc. | | -| (Inline) Start Tag | An inline tag that together with a corresponding end tag enclose a localizable string. | | -| (Inline) End Tag | An inline tag that together with a corresponding start tag enclose a localizable string. | | -| Paragraph Unit | A piece of bilingual content that can be translated as one continous content unit during localization. This is typically a single paragraph, heading, table cell, etc. It may have both a source and a target language component (or only a source component before it has been translated). | (no real equivalent in TRADOS or SDLX); trans-unit in XLIFF| -| Segment | A piece of source or target language content inside a paragraph unit that can be treated as one unit when being processed with a localization tool such as a translation memory. A segment is in most cases a sentence. | Comparable to the source or target segment of a translation unit.| -| Extract | The process of extracting localizable content from native source language files, typically to produce bilingual files for translation. | Convert, Forward Convert, to Filter| -| Generate | The process of converting translated bilingual files into native target language files. | Back-convert, Save Target As, Clean-up| -| Semi-WYSIWYG Formatting | Display properties of the text that help translators to better visualize the layout of the document that is being translated. The semi-WYSIWYG formatting information is purely informational, it carries no actual formatting that would affect the translated files. The formatting information that applies to the actual document in its native format is only contained in the tags. | elements in TRADOStag, formatting in TagEditor| +This table defines the terms used in the File Type Support Framework. + +| Term | Explanation | Synonym, older term, or related concept | +| --- | --- | --- | +| File Type Support Framework | File Type Support Framework 2 API. | Trados Filter Framework 1.0 | +| Source | The source language that provides the localizable content. | Original | +| Target | A target language that receives the translated content. | Translated | +| Native | Content in a single language, either source or target, usually before or after localization. | Monolingual; original file type | +| Bilingual | Content under localization, usually as paired source and target content. | TRADOStag, XLIFF, Workbench RTF | +| Text | Localizable text content. | | +| Tag | Content that must remain unchanged during localization. Editing tools such as TagEditor or SDLEdit protect tags from accidental changes. | | +| Inline Tag | A tag that appears inside localizable content and that users might move during localization. Typical examples include links, local formatting overrides, and embedded graphics. | Internal Tag, tw4winInternal | +| Structure Tag | A tag that appears outside localizable content. These tags usually represent document structure, such as paragraphs, tables, headers, and footers. | External Tag, tw4winExternal | +| (Inline) Placeholder Tag | An inline tag that acts as a stand-alone element. Typical examples include index markers and inline graphics. | | +| (Inline) Start Tag | An inline tag that works with a corresponding end tag to enclose a localizable string. | | +| (Inline) End Tag | An inline tag that works with a corresponding start tag to enclose a localizable string. | | +| Paragraph Unit | A unit of bilingual content that translators can process as one continuous unit during localization. A paragraph unit usually maps to a single paragraph, heading, or table cell. It can contain both source and target content, or only source content before translation starts. | No direct equivalent in TRADOS or SDLX; trans-unit in XLIFF | +| Segment | A unit of source or target content inside a paragraph unit that localization tools can process independently, for example through translation memory. In most cases, a segment is a sentence. | Comparable to the source or target segment of a translation unit | +| Extract | The process of extracting localizable content from native source-language files, usually to create bilingual files for translation. | Convert, Forward Convert, to Filter | +| Generate | The process of converting translated bilingual files into native target-language files. | Back-convert, Save Target As, Clean-up | +| Semi-WYSIWYG Formatting | Display properties that help translators visualize the document layout during translation. This information remains informational only and does not apply actual formatting to the translated files. The native-format file stores the actual formatting in the tags. | elements in TRADOStag, formatting in TagEditor | diff --git a/apiconcepts/filetypesupport/user_communication_through_messaging.md b/apiconcepts/filetypesupport/user_communication_through_messaging.md index afe709b270..613b0e19f3 100644 --- a/apiconcepts/filetypesupport/user_communication_through_messaging.md +++ b/apiconcepts/filetypesupport/user_communication_through_messaging.md @@ -1,46 +1,44 @@ -User Communication Through Messaging -== +# User Communication Through Messaging -In this chapter you will learn how to provide users with helpful information on why a given file cannot be supported by the file type plug-in. +This section explains how to tell users why the file type plug-in does not support a file. -Enhance the File Sniffer to Output a Detailed Message --- +## Enhance the file sniffer to output a detailed message -When the file sniffer determines that a given file cannot be supported, the framework will generate the following default message: +When the file sniffer determines that it cannot support a file, the framework generates the following default message: ![FileTypeNotSupported](images/FileTypeNotSupported.jpg) -However, it may be useful to provide users with more information on why a given file is not supported, so that they can edit the file and resolve the problem. Example: Var:ProductName cannot process Microsoft Word documents that contains any pending changes. When users try to open such a DOC file, they will receive a message that points out this particular problem. They can then open the source document in Microsoft Word, accept or reject all pending changes, thereby resolving the problem. +Provide a more specific message when possible so that users can correct the problem. For example, Var:ProductName cannot process Microsoft Word documents that contain pending changes. When users open such a DOC file, the application can explain the problem. Users can then open the source document in Microsoft Word and accept or reject the pending changes. -Remember that our sample file type plug-in checks for the presence of the string **[Version=n]** in the first line. If this string is not present, the sniffer should throw a more detailed message, which states the cause of the problem. +The sample file type plug-in checks whether the first line contains **[Version=n]**. If the string is missing, the sniffer should report a detailed message that explains the problem. -Let us consolidate the message texts thrown by the sniffer in another resources file. Add an additional resources file (e.g. **StringResources.resx**) to your project. Enter two resource names and values as shown below: +Store the sniffer messages in a separate resource file. Add another resource file, for example **StringResources.resx**, to your project. Then add two resource names and values, as shown below: ![SnifferMessages](images/SnifferMessages.jpg) -Now enhance the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method as outlined below: apply the [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method to the locMsgReporter object, which is returned by the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method: +Update the [Sniff](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileSniffer.yml#Sdl_FileTypeSupport_Framework_NativeApi_INativeFileSniffer_Sniff_System_String_Sdl_Core_Globalization_Language_Sdl_Core_Globalization_Codepage_Sdl_FileTypeSupport_Framework_NativeApi_INativeTextLocationMessageReporter_Sdl_Core_Settings_ISettingsGroup_) method to call [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) on the `messageReporter` object that the method receives: # [C#](#tab/tabid-1) ```cs -locMsgReporter.ReportMessage(this, nativeFilePath, +messageReporter.ReportMessage(this, nativeFilePath, ErrorLevel.Error, StringResources.Sniffer_Message, StringResources.Sniffer_Location); ``` *** -The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method takes a number of parameters such as the error level. Since not being able to open a file is, of course, a critical problem, we choose the highest severity level, i.e. Error. From our string resources file, we retrieve the descriptive texts, which provide detailed information to the user. -Instead of just returning the default generic message, the file sniffer will now generate the following output: +The [ReportMessage](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.IBasicMessageReporter.yml#Sdl_FileTypeSupport_Framework_NativeApi_IBasicMessageReporter_ReportMessage_System_Object_System_String_Sdl_FileTypeSupport_Framework_NativeApi_ErrorLevel_System_String_System_String_) method accepts several parameters, including the error level. Because the plug-in cannot open the file, use the highest severity level: `Error`. The string resource file supplies the descriptive text that explains the problem to the user. + +Instead of returning only the generic default message, the file sniffer now generates the following output: ![DetailedErrorMessage](images/DetailedErrorMessage.jpg) >[!NOTE] > ->Since file type plug-ins can also be used in server-based scenarios, they cannot always present information to users like 'normal', Windows-based applications do, e.g. by using a message box or by directly updating the user interface of the application. Such behavior could cause the server processing to hang, as there is no user to interact with. +> File type plug-ins can also run in server-based scenarios. In those scenarios, the plug-in cannot always present information the way a Windows application does, for example by showing a message box or updating the application UI directly. That behavior can cause server processing to hang because no user is available to respond. -Putting it All Together --- +## Put it all together -Your enhanced file sniffer class should now look as shown below: +Your enhanced file sniffer class should now look like this: # [C#](#tab/tabid-2) ```cs @@ -51,18 +49,16 @@ using Sdl.Core.Settings; namespace Sdk.FileTypeSupport.Samples.SimpleText { - // the file sniffer component determines whether a given file - // can be processed by the filter or not public class SimpleTextSniffer : INativeFileSniffer { public SniffInfo Sniff(string nativeFilePath, Language suggestedSourceLanguage, Codepage suggestedCodepage, INativeTextLocationMessageReporter messageReporter, ISettingsGroup settingsGroup) { - SniffInfo fileInfo = new SniffInfo(); + var fileInfo = new SniffInfo(); - using (StreamReader _reader = new StreamReader(nativeFilePath)) + using (var reader = new StreamReader(nativeFilePath)) { - if (_reader.ReadLine().StartsWith("[Version=")) + if (reader.ReadLine().StartsWith("[Version=")) { fileInfo.IsSupported = true; } @@ -77,24 +73,14 @@ namespace Sdk.FileTypeSupport.Samples.SimpleText return fileInfo; } - - #region INativeFileSniffer Members - - - #endregion } } ``` *** -See Also --- - - - -[Implementing the File Sniffer](implementing_the_file_sniffer.md) - +## See also +- [Implementing the File Sniffer](implementing_the_file_sniffer.md) >[!NOTE] > diff --git a/apiconcepts/filetypesupport/using_context_information.md b/apiconcepts/filetypesupport/using_context_information.md index aaca8a533a..5a3eef58e4 100644 --- a/apiconcepts/filetypesupport/using_context_information.md +++ b/apiconcepts/filetypesupport/using_context_information.md @@ -1,25 +1,34 @@ -Using context information -====== -If applicable, a file type plug-in should not only extract translatable text to an intermediary file, it should also make context information available. This allows translators and editors to determine easily whether a string is a headline, table cell content, etc. (without actually seeing the real document layout). This kind of information can help translators do their job more effectively. +# Using context information -File type plug-ins effectively separate translatable content from the document layout. This offers the advantage of translators/editors being able to focus on the content. However, it is often useful for users to know whether the string they are currently translating or editing belongs to a table cell, footnote, etc. This is why a good file type plug-in should present such context information to the user. Any context information is displayed in the document structure column of the editor. To save space this column shows a short display code, e.g. **H** for headline. By moving the mouse pointer over the display code, the full description is shown in a tooltip. By double-clicking the display code, users can display even more information (if available). +Where applicable, a file type plug-in should extract translatable text and expose context information in the intermediary file. Context information helps translators and editors identify content types such as headlines, table cells, and footnotes without opening the original document layout. - +## Why context information matters -Example of a context display code for text box content extracted from a PPT document: +File type plug-ins separate translatable content from document layout so users can focus on the text. Context information adds another layer of guidance by showing where a segment came from. For example, users can tell whether a string belongs to a table cell or a footnote. - +## How context information appears in the editor -Double-clicking the document structure column reveals additional information, in this case the context information on text box content contained on a PowerPoint slide. +Var:ProductName shows context information in the document structure column of the editor. To save space, the column uses short display codes, such as **H** for headline. Users can hover over the code to see the full description in a tooltip. -Also, Var:ProductName can display a document structure tree in the navigation pane on the left-hand side of the application. This tree allows users to quickly navigate in the document, for example, by clicking the corresponding headlines. +Users can also double-click the display code to see additional information, when available. - + -Example of a document structure tree, which helps users quickly navigate to the corresponding sections in the editor. In the example below the structure tree displays the level 1 and 2 headings found in a Microsoft Word document. +Example of a context display code for text box content extracted from a PPT document. -See Also --------- -[Implementing the File Parser](implementing_the_file_parser.md) + -[Adding Context Information](adding_context_information.md) +Double-clicking the document structure column reveals additional information about the text box content on the PowerPoint slide. + +## Use the document structure tree + +Var:ProductName can also display a document structure tree in the navigation pane on the left side of the application. The tree lets users navigate quickly to the corresponding sections in the document. + + + +Example of a document structure tree that helps users navigate to the corresponding sections in the editor. In this example, the tree displays level 1 and level 2 headings found in a Microsoft Word document. + +## See also + +- [Implementing the File Parser](implementing_the_file_parser.md) +- [Adding Context Information](adding_context_information.md) diff --git a/apiconcepts/filetypesupport/using_quickinserts.md b/apiconcepts/filetypesupport/using_quickinserts.md index 6c7b5d661b..b62fd432a8 100644 --- a/apiconcepts/filetypesupport/using_quickinserts.md +++ b/apiconcepts/filetypesupport/using_quickinserts.md @@ -1,21 +1,34 @@ -Using QuickInserts -===== -The QuickInsert feature allows users to insert placeholder tags, tag pairs, special characters, etc. into the target text with the click of a toolbar button or through a keyboard shortcut. That way users have easy access to, for example, commonly used special characters that are difficult to type on their keyboards. +# Using QuickInserts - Var:ProductName allows you to insert tags that occur in a source segment into the corresponding target segment. However, sometimes you may need to insert tags or text (e.g. special characters) that do not occur in the source segment. Example: The source segment does not contain bold formatting, however, you want to apply bold formatting in the translation to highlight a particular string. Another example: The source segment uses straight quotes, while the target language requires smart quotes. Both examples are use cases for QuickInserts. Through QuickInserts, users can quickly insert the tags or characters that they require in the target segment. +QuickInserts let users insert placeholder tags, tag pairs, and special characters in target text by using a toolbar button or keyboard shortcut. This gives quick access to characters that are hard to type. -When developing a file type plug-in you should consider which tags or special characters are most likely to be used in the file format that you need to process. Most file formats will use common character formatting such as bold, italics, and underline. It might therefore make sense to define QuickInserts for those particular types of character formatting. Very often, users require e.g. smart quotes , which may be difficult to type on certain keyboards. It might therefore also make sense to define special QuickInserts e.g. for French quotes, smart quotes, etc. +Var:ProductName inserts tags from a source segment into the target segment. In some cases, users must insert tags or text that do not appear in the source segment. For example: -End users can define and customize QuickInserts themselves through the application GUI up to a certain degree. However, some things can only be done programmatically by defining them in the file type plug-in assembly. For example, Var:ProductName allows users to define QuickInserts for single characters, strings and string pairs. Defining QuickInsert items for tags (e.g. for applying bold formatting) is currently only possible programmatically, not through the application user interface. +- The source segment has no bold formatting, but the translation needs bold text for emphasis. +- The source segment uses straight quotes, but the target language needs smart quotes. - +QuickInserts support these scenarios. -The QuickInsert toolbar as defined for the Microsoft Word file type. Through the toolbar buttons you can insert, for example, quotes as well as a *br* tag to insert line breaks. +## Choose QuickInserts for Your File Type -In addition to the QuickInsert toolbar users can also open a separate **Insert Tag** window, from which they can insert QuickInsert items. +When you develop a file type plug-in, identify the tags and special characters users will likely need. Most file formats use common formatting such as bold, italics, and underline. Users also often need characters such as smart quotes or French quotes that are difficult to type on some keyboards. - +Define QuickInserts for these common needs. -See Also -------- -[Implementing QuickInsert Functionality](implementing_quickinsert_functionality.md) +## Configure QuickInserts + +Users can create and customize some QuickInserts in the application GUI. Other QuickInserts must be defined in code in the file type plug-in assembly. + +For example, Var:ProductName lets users define QuickInserts for single characters, strings, and string pairs. Only programmatic configuration can define QuickInsert items for tags, such as bold formatting. + +## QuickInsert Toolbar + +![QuickInsert toolbar for Microsoft Word file type. It includes buttons for quotes and a *br* tag for line breaks.](images/QuickTag01.jpg) + +Users can also open the **Insert Tag** window to insert QuickInsert items. + +![Insert Tag window for QuickInserts.](images/QuickTag02.jpg) + +## See also + +- [Implementing QuickInsert Functionality](implementing_quickinsert_functionality.md) diff --git a/apiconcepts/filetypesupport/verifying_files.md b/apiconcepts/filetypesupport/verifying_files.md index 470a867384..e8190e5a3c 100644 --- a/apiconcepts/filetypesupport/verifying_files.md +++ b/apiconcepts/filetypesupport/verifying_files.md @@ -1,27 +1,30 @@ -Verifying files -==== -Files can be verified for a number of different criteria. The most common example of file verification is the standard tag verification, which checks whether the user failed to insert tags into the translation. You can equip your file type plug-in with verification functionality, for example, by developing an additional verifier plug-in. +# Verifying files + +You can verify files against specific criteria. A common example is tag verification, which detects missing tags in the translation. To add verification to your file type plug-in, develop an additional verifier plug-in. -Verification example: The interactive verification displays a yellow warning icon next to the target segment as it is missing an inline tag. +Interactive verification shows a yellow warning icon next to the target segment when the translation is missing an inline tag. + +## Example: Verify Microsoft Excel worksheet names -One example of a format that requires a particular type of verification is Microsoft Excel. Excel worksheet names must not exceed 31 characters. If a translator enters more than 31 characters for a worksheet name, the corresponding native target file cannot be generated from the intermediary document. This is why the standard file type plug-in for Microsoft Excel files checks for any worksheet names that violate this length limit and generate an error messsage if that is the case. +Microsoft Excel worksheet names cannot exceed 31 characters. If a translator enters a longer worksheet name, Var:ProductName cannot generate the native target file from the intermediary document. The standard Microsoft Excel file type plug-in checks this limit and generates an error message when the translation exceeds it. -The interactive verification, which is part of the file type plug-in for MS Excel files displays a red error icon next to the target segment, as the worksheet name translation exceeds the length limit of 31 characters. +The interactive verifier in the Microsoft Excel file type plug-in shows a red error icon next to the target segment when the translated worksheet name exceeds 31 characters. -The error message is also shown in the **Messages** window of Var:ProductName with an error description, the file in which the error was found and the file type plug-in which has thrown the error. By double-clicking the error message in this window the user navigates to the exact segment in the side-by-side editor. +Var:ProductName also lists the error in the **Messages** window. The message includes the error description, the file that contains the issue, and the file type plug-in that reported it. When the user double-clicks the message, Var:ProductName opens the exact segment in the side-by-side editor. -A verification can be triggered interactively when the users confirms a segment. If a problem has been found in that particular segment, a symbol (error = red, warning = yellow, note = white) will be displayed next to the segment in question. For the above example (i.e. Excel worksheet names) the severity level is error (red), as this is a serious problem, which prevents users from generating the target MS Excel file after tranlation. +## Run verification + +Verification can run interactively when the user confirms a segment. If the verifier finds a problem, it displays a symbol next to that segment: error (red), warning (yellow), or note (white). In the Excel worksheet example, the verifier reports an error because the issue prevents target file generation. -Users can also run a batch verification on the entire document (through the menu command **Tools** > **Verify**) or they can apply a verfication to several documents by running a **Verify** batch task. The latter will generate a detailed report on any issues found in the documents in question. +Users can also run verification for an entire document from **Tools** > **Verify**. To verify multiple documents, run the **Verify** batch task. The batch task generates a detailed report for the selected documents. -See Also ------- -[What is the Verification Framework?](what_is_the_verification_framework.md) +## See also -[User Communication Through Messaging](user_communication_through_messaging.md) +- [What is the Verification Framework?](what_is_the_verification_framework.md) +- [User Communication Through Messaging](user_communication_through_messaging.md) diff --git a/apiconcepts/filetypesupport/what_a_file_type_plugin_must_do.md b/apiconcepts/filetypesupport/what_a_file_type_plugin_must_do.md index 763236a225..1624afc16a 100644 --- a/apiconcepts/filetypesupport/what_a_file_type_plugin_must_do.md +++ b/apiconcepts/filetypesupport/what_a_file_type_plugin_must_do.md @@ -1,27 +1,33 @@ -What a File Type Plug-in Must Do -== - -Suppose you want to develop a filter that allows you to translate files Var:ProductName which are not supported by the default installation of the product. - -Your proposed filter should do the following: - -* The new file type must be listed in the File type dropdown list of the Var:ProductName *Open dialog*, see [Opening a document for translation](opening_a_document_for_translation.md) chapter. -* Var:ProductName must be able to open the new file type and display it, see [The File Parser](the_file_parser.md) chapter (extraction). -* Upon opening the file, the original format needs to be converted into SDLXliff by the File Type Support Framework. -* It must be possible to batch-translate/analyze the new file format in Var:ProductName. -* The view of Var:ProductName needs to display the text to translate. Any untranslatable bits need to be displayed as tags or hidden from the translator. -* The display should also include (semi-)WYSIWYG formatting, i.e. bold, italic, underline, etc., see [Text Formatting](text_formatting.md) -* Optional: Var:ProductName should be able to display the document in its native format using the Realtime Preview feature. -* The user must be able to translate the text using Var:ProductName. -* The user must be able to save the file in SDLXliff format. -* The user must be able to save the fully translated file in the target format (generation), see [The File Writer](the_file_writer.md). -* The filter should be able check the validity of the target document during generation (verification). -* The user must be able to change any required filter settings, see [The text formatting](filter_ui_settings.md). -* If any problem occurs during any step of translation workflow, the filter should notify the user accordingly, see [Reporting problems](reporting_problems.md). Since filters may also be used in a server envinroment, the filter should use the built-in feature of the File Type Support Framework for displaying messages, where no user interaction is required. - -Based on FFAPI we can create [monolingual](https://en.wikipedia.org/wiki/Monolingualism) (native) parsers, which can read in the translatable source language for a file type during the content extracttion phase and write the translated text back to a copy of the original document during a content generation phase, or a bilingual parser, which can read both the source and the target text from a bilingual document that contains the original source language text and the translated target language text. A typical example of a monolingual file type is an MS Word (* *.doc*)document; a typical example of a [bilingual](https://en.wikipedia.org/wiki/Multilingualism) file type would be a TradosTag (* *.ttx*) document. - -As you can see, the list of things that the filter will ultimately accomplish is rather comprehensive. In the next chapters we will take you step-by-step through the process of developing a native and a bilingual filter (highly simplified filters) and demonstrate most of the required functions that a filter should implement. +# What a File Type Plug-in Must Do + +If you want to develop a filter for a file format that Var:ProductName does not support by default, your plug-in should provide the following capabilities. + +## Required capabilities + +* List the new file type in the **File type** drop-down in the Var:ProductName **Open** dialog. For more information, see [Opening a document for translation](opening_a_document_for_translation.md). +* Open the new file type in Var:ProductName and display its content. For more information, see [The File Parser](the_file_parser.md). +* Convert the original file format to SDLXLIFF during extraction. +* Support batch tasks such as translation and analysis for the new file format. +* Display the translatable text in Var:ProductName. Render non-translatable content as tags or hide it from the translator. +* Preserve semi-WYSIWYG formatting such as bold, italic, and underline. For more information, see [Text Formatting](text_formatting.md). +* Optionally display the document in its native format through the Realtime Preview feature. +* Let users translate the text in Var:ProductName. +* Let users save the file in SDLXLIFF format. +* Generate the fully translated target file. For more information, see [The File Writer](the_file_writer.md). +* Validate the target document during generation. +* Let users change any required filter settings. For more information, see [Filter UI settings](filter_ui_settings.md). +* Report problems at any stage of the translation workflow. For more information, see [Reporting problems](reporting_problems.md). Because filters can also run in server environments, use the built-in File Type Support Framework messaging features that do not require user interaction. + +## Parser models + +The File Type Support Framework API (FFAPI) lets you create monolingual and bilingual parsers. + +* A [monolingual](https://en.wikipedia.org/wiki/Monolingualism) parser reads the translatable source text during extraction and writes the translated text back during generation. A typical monolingual file type is a Microsoft Word `*.doc` document. +* A [bilingual](https://en.wikipedia.org/wiki/Multilingualism) parser reads both source and target text from a bilingual document. A typical bilingual file type is a TradosTag `*.ttx` document. + +## Next steps + +The following chapters walk through the process of developing simplified native and bilingual filters. They also demonstrate most of the functions that a file type plug-in should implement. >[!NOTE] diff --git a/apiconcepts/filetypesupport/what_can_you_do_with_the_file_type_support_sdk.md b/apiconcepts/filetypesupport/what_can_you_do_with_the_file_type_support_sdk.md deleted file mode 100644 index 49e70d7841..0000000000 --- a/apiconcepts/filetypesupport/what_can_you_do_with_the_file_type_support_sdk.md +++ /dev/null @@ -1,11 +0,0 @@ -What can you do with the File Type Support SDK? -==== -Below you will find a number of examples of what you can do with the File Type Support Framework SDK. Note that several example projects are available with this documentation. - -* Let us assume that you need to process a document format that is not supported out-of-the box by Var:ProductName. This SDK includes a sample project that demonstrates a filter for localizing custom text files. -* Suppose that the target segments must not exceed a user-configurable length limit or must not be below a specific length limit. To make sure this requirement is fulfilled in all target documents, you can develop a custom plug-in that applies to all document formats. -* Suppose you need to process an XML format in which the tags contain information on the specific length limit. With this SDK, you can create a custom file type and enhance it with an extension that checks whether the length limit has been observed. -* Imagine that all headings of an HTML document must not be translated, but rather stay in the original language. With this SDK, you can develop an extension that allows you to check whether headings that are not supposed to be translated have been accidentally changed by the user. - - -This SDK contains numerous examples of how to develop plug-ins to meet specific localization requirements. Plug-ins can relieve you from time-consuming, tedious and ultimately error-prone manual tasks, such as counting characters or copy/pasting multiple segments. diff --git a/apiconcepts/filetypesupport/what_is_the_verification_framework.md b/apiconcepts/filetypesupport/what_is_the_verification_framework.md index 970d7f9026..2cb616f0a6 100644 --- a/apiconcepts/filetypesupport/what_is_the_verification_framework.md +++ b/apiconcepts/filetypesupport/what_is_the_verification_framework.md @@ -1,42 +1,33 @@ -What is the Verification Framework? -== +# What is the Verification Framework? -The verification framework is the service build up on the top of the File Type Support Framework. It is used for the verification of translated documents. +The verification framework provides built-in verification services on top of the File Type Support Framework. It checks translated documents for quality and compliance issues. -Users can verify documents in three different ways: +Users can verify documents in three ways: -* Interactive verification: the segment is verified immediately when it is confirmed by the user. -* Document verification (on-demand verification): all target segments of the document are checked when the user presses the F8 key in Var:ProductName. -* Batch verification: when user perform a **Verify** batch task in the project (e.g. in the Files view of Var:ProductName). +* **Interactive verification**: The system verifies each segment immediately when the user confirms it. +* **Document verification (on-demand verification)**: The system checks all target segments of the document when the user presses the F8 key in Var:ProductName. +* **Batch verification**: The system verifies documents when the user runs a **Verify** batch task in the project (for example, in the Files view of Var:ProductName). The verification framework supports three types of verification plug-ins: - * **Bilingual verifiers**: Bilingual verifiers are used to check documents of a particular file type for potential problems. Example: sheet names of MS Excel files must not be longer than 31 characters. If a sheet name exceeds this length limit during translation, the intermediary (SDLXliff) file cannot be converted back into a valid Excel target file. To check a translation for violations of this length limit, you can enhance the MS Excel filter with a bilingual verification plug-in that points out sheet name translations that are longer than 31 characters. - * **Native verifiers**: While bilingual verifiers work on the intermediary (SDLXliff) document, native verifiers are applied to the native output format, e.g. DOC, MIF, XML, etc. Example: You have created a File Type Component Builder for a particular XML document type in which the length of a particular element must not exceed a certain number of characters. To check the validity of the translated XML output files, you can enhance your XML File Type Component * Builder with a verification plug-in that checks whether the maximum length in the XML target file has been exceeded. - * **Global verifiers**: Global verifiers are not associated with a particular file type. They rather apply to any file type. By default, Var:ProductName is delivered with two global verifiers: **QA Checker** and **Terminology Verifier**. These plug-ins are used to check any inermediary (SDLXliff) files for, e.g. number and punctuation errors, failure to use the correct terminology, etc. This means that global verifiers are used to check bilingual documents for problems that are not specific to a particular file type. The verification framework allows you to develop additional global verifiers to check documents for criteria that are not covered by the standard QA Checker and Terminology Verifier plug-ins. +* **Bilingual verifiers**: These plug-ins check documents of a particular file type for problems in the intermediary (SDLXliff) format. For example, sheet names in Microsoft Excel files must not exceed 31 characters. If a sheet name exceeds this limit during translation, the SDLXliff file cannot convert back to a valid Excel target file. You can enhance the MS Excel filter with a bilingual verification plug-in to identify sheet name translations longer than 31 characters. +* **Native verifiers**: While bilingual verifiers work on SDLXliff documents, native verifiers check the native output format (for example, DOC, MIF, or XML). For instance, if you create a File Type Component Builder for an XML document type with specific element length constraints, you can add a verification plug-in to check whether translated XML output files exceed the maximum allowed length. +* **Global verifiers**: These plug-ins apply to any file type rather than a specific format. Var:ProductName includes two default global verifiers: **QA Checker** and **Terminology Verifier**. These check SDLXliff files for issues like number errors, punctuation inconsistencies, and incorrect terminology use. Global verifiers identify language-related problems that are not specific to a particular file type. You can develop additional global verifiers to check documents for criteria not covered by the standard QA Checker and Terminology Verifier. -See Also --- +## Reference -**Reference** +- [IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) +- [INativeFileVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml) +- [IGlobalVerifier](../../api/verification/Sdl.Verification.Api.IGlobalVerifier.yml) -[IBilingualVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.BilingualApi.IBilingualVerifier.yml) +## See Also -[INativeFileVerifier](../../api/filetypesupport/Sdl.FileTypeSupport.Framework.NativeApi.INativeFileVerifier.yml) - -[IGlobalVerifier](../../api/verification/Sdl.Verification.Api.IGlobalVerifier.yml) - - - -[How to Create a Native Verifier](create_a_native_verifier_introduction.md) - -[How to Create a Bilingual Verifier](create_a_bilingual_verifier_introduction.md) - -[How to Create a Global Verifier](global_verifier_introduction.md) - -[Verifying files](verifying_files.md) +- [How to Create a Native Verifier](create_a_native_verifier_introduction.md) +- [How to Create a Bilingual Verifier](create_a_bilingual_verifier_introduction.md) +- [How to Create a Global Verifier](global_verifier_introduction.md) +- [Verifying files](verifying_files.md) >[!NOTE] > -> This content may be out-of-date. To check the latest information on this topic, inspect the libraries using the Visual Studio Object Browser. +>This content may be out-of-date. Inspect the libraries in the Visual Studio Object Browser to verify the latest information on this topic. diff --git a/apiconcepts/toc.yml b/apiconcepts/toc.yml index b77d8c53ef..adffacea15 100644 --- a/apiconcepts/toc.yml +++ b/apiconcepts/toc.yml @@ -18,42 +18,36 @@ - name: File Type Support href: filetypesupport/overview.md items: - - name: Introduction to this SDK + - name: Overview + href: filetypesupport/overview.md + - name: How Translators Work + href: filetypesupport/how_translators_work.md items: - - name: File Type Framework Overview - href: filetypesupport/overview.md - - name: What can you do with the File Type Support SDK? - href: filetypesupport/what_can_you_do_with_the_file_type_support_sdk.md - - name: How Translators Work - href: filetypesupport/how_translators_work.md - items: - - name: Opening a document for translation - href: filetypesupport/opening_a_document_for_translation.md - - name: Creating Projects - href: filetypesupport/creating_projects.md - - name: Merging files - href: filetypesupport/merging_files.md - - name: Moving files between machines - href: filetypesupport/moving_files_between_machines.md - - name: File type settings - href: filetypesupport/file_type_settings.md - - name: Using context information - href: filetypesupport/using_context_information.md - - name: Tag display modes - href: filetypesupport/tag_display_modes.md - - name: Using QuickInserts - href: filetypesupport/using_quickinserts.md - - name: Verifying files - href: filetypesupport/verifying_files.md - - name: Previewing files - href: filetypesupport/previewing_files.md - - name: Saving to different file types - href: filetypesupport/saving_to_different_file_types.md + - name: Opening a document for translation + href: filetypesupport/opening_a_document_for_translation.md + - name: Creating Projects + href: filetypesupport/creating_projects.md + - name: Merging files + href: filetypesupport/merging_files.md + - name: Moving files between machines + href: filetypesupport/moving_files_between_machines.md + - name: File type settings + href: filetypesupport/file_type_settings.md + - name: Using context information + href: filetypesupport/using_context_information.md + - name: Tag display modes + href: filetypesupport/tag_display_modes.md + - name: Using QuickInserts + href: filetypesupport/using_quickinserts.md + - name: Verifying files + href: filetypesupport/verifying_files.md + - name: Previewing files + href: filetypesupport/previewing_files.md - name: Used Terminology href: filetypesupport/used_terminology.md - name: The File Type Support Framework items: - - name: File Type Support - Overview + - name: Overview href: filetypesupport/file_type_support_overview.md - name: The Filter Component Builder href: filetypesupport/the_filter_component_builder.md