--- source_files: - DataPRO/Modules/Groups/GroupChannelList/Resources/TranslateExtension.cs - DataPRO/Modules/Groups/GroupChannelList/Resources/StringResources.Designer.cs generated_at: "2026-04-17T15:58:50.253166+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "fc71a9ad19b8ef2b" --- # Documentation: GroupChannelList Resources Module ## 1. Purpose This module provides localization infrastructure for the GroupChannelList feature within the DataPRO Groups module. It consists of a WPF XAML markup extension (`TranslateExtension`) that enables declarative string localization in XAML bindings, backed by an auto-generated strongly-typed resource class (`StringResources`) containing localized strings for channel configuration UI elements, parameter labels, validation messages, and user-facing text. The module supports the configuration and display of various channel types including Analog, CAN, Digital I/O, Squib, Stream, and UART channels. --- ## 2. Public Interface ### TranslateExtension (Markup Extension) **Class Definition:** ```csharp [MarkupExtensionReturnType(typeof(string))] public class TranslateExtension : MarkupExtension ``` **Constructor:** ```csharp public TranslateExtension(string key) ``` - Creates an instance with the specified resource key to look up. **Public Method:** ```csharp public override object ProvideValue(IServiceProvider serviceProvider) ``` - Returns the localized string for the key stored in `_key` by querying `StringResources.ResourceManager.GetString(_key)`. - Returns `NotFound` ("#stringnotfound#") if `_key` is null or empty. - Returns `NotFound + " " + _key` (e.g., "#stringnotfound# SomeKey") if the resource lookup returns null. **Private Constants:** - `private const string NotFound = "#stringnotfound#"` — Fallback value for missing keys. --- ### StringResources (Auto-Generated Resource Class) **Class Definition:** ```csharp internal class StringResources ``` - Internal class; not accessible outside the `GroupChannelList.Resources` namespace. **Static Properties:** | Property | Description (from source comments) | |----------|-------------------------------------| | `ResourceManager` | Returns cached `ResourceManager` instance for this assembly. | | `Culture` | Gets/sets `CultureInfo` for resource lookups. | **Resource String Properties (selected):** | Property | Default Text | |----------|--------------| | `AnalogParameter_ACCouplingEnable` | "AC coupling enabled" | | `AnalogParameters_Capacity` | "Sensor max range" | | `AnalogParameters_CFC` | "Channel filter class" | | `AnalogParameters_InitialOffset` | "Initial offset" | | `AnalogParameters_MaximumUsage` | "Maximum Usage" | | `AnalogParameters_Polarity` | "Polarity" | | `AnalogParameters_Range` | "Channel full-scale" | | `AnalogParameters_Sensitivity` | "Sensitivity" | | `AnalogParameters_Units` | "Units" | | `AnalogParameters_UsageCount` | "Usage Count" | | `AnalogParameters_UserValue1/2/3` | "User Value 1/2/3" | | `AnalogParameters_ZeroMethod` | "Zero Method" | | `AnalogParameters_ZeroMethodEnd` | "End (sec)" | | `AnalogParameters_ZeroMethodStart` | "Start (sec)" | | `CanParameters_ArbBaseBitrate` | "Arb/Base Bitrate" | | `CanParameters_ArbBaseSJW` | "Arb/Base SJW" | | `CanParameters_DataBitrate` | "Data Bitrate" | | `CanParameters_DataSJW` | "Data SJW" | | `CanParameters_FileType` | "FileType" | | `CanParameters_IsFD` | "CAN is FD" | | `DigitalInParameters_ActiveValue` | "Active value" | | `DigitalInParameters_DefaultValue` | "Default value" | | `DigitalInParameters_InputMode` | "Input mode" | | `DigitalOutParameters_Delay` | "Delay (ms)" | | `DigitalOutParameters_Duration` | "Duration (ms)" | | `DigitalOutParameters_LimitDuration` | "Limit duration" | | `DigitalOutParameters_OutputMode` | "Output mode" | | `SquibParameters_Current` | "Current (A)" | | `SquibParameters_Delay` | "Delay (ms)" | | `SquibParameters_Duration` | "Duration (ms)" | | `SquibParameters_FireMode` | "Fire mode" | | `SquibParameters_LimitDuration` | "Limit duration" | | `StreamInParameters_UDPAddress` | "UDP Address" | | `StreamOutParameters_DataChannelId` | "Data channel id" | | `StreamOutParameters_IENA_Key` | "IENA key" | | `StreamOutParameters_IENA_SourcePort` | "Source port" | | `StreamOutParameters_IRIGTimeDataPacketIntervalMs` | "IRIG time data packet interval (ms)" | | `StreamOutParameters_StreamProfile` | "Stream profile" | | `StreamOutParameters_TimeChannelId` | "Time channel id" | | `StreamOutParameters_TMATSIntervalMs` | "TMATS interval (ms)" | | `StreamOutParameters_TMNS_MessageId` | "Message Id" | | `StreamOutParameters_TMNS_MinorPerMajor` | "Minor per major" | | `StreamOutParameters_TMNS_SubFrameId` | "Subframe Id" | | `StreamOutParameters_TMNS_TMATSPort` | "TMATS port" | | `StreamOutParameters_TmNSConfig` | "TmNS config" | | `StreamOutParameters_UDPAddress` | "UDP Address" | | `UartParameters_BaudRate` | "Baud rate" | | `UartParameters_DataBits` | "Data bits" | | `UartParameters_DataFormat` | "Data format" | | `UartParameters_FlowControl` | "Flow control" | | `UartParameters_Parity` | "Parity" | | `UartParameters_StopBits` | "Stop bits" | | `ChannelName` | "Channel name" | | `ChannelType` | "Type" | | `Channels` | " channel(s) in " | | `Clear` | "Clear" | | `Delete` | "Delete" | | `DisplayName` | "Display name" | | `DisplayOrder` | "Display order" | | `DragAndDropFilterWarning` | "Drag and drop operation completed. Note that the table is currently being filtered..." | | `DuplicateSensor` | "Sensor appears more than once" | | `EnterValue` | "Enter value" | | `GlobalRangeCAC` | "Global range (CAC)" | | `Group` | "Group" | | `GroupLower` | "group" | | `Hardware` | "Hardware" | | `IEPESupport` | "IEPE support" | | `IntervalOn` | "On" | | `InvalidAnalogAssignment` | "Sensor {0} can not be assigned to channel {1}" | | `InvalidDigitalInputAssignment` | "DigitalInput {0} can not be assigned to channel {1}" | | `InvalidDigitalOutputAssignment` | "DigitalOutput {0} can not be assigned to channel {1}" | | `InvalidExcitationAssignment` | "Sensor {0} does not support any of the excitation options provided by channel {1}" | | `InvalidLine` | "Invalid pasted group channel, line: {0}" | | `InvalidSensor` | "Invalid sensor, line: {0}" | | `InvalidSquibAssignment` | "Squib {0} can not be assigned to channel {1}" | | `ISOAndUserCode` | "ISO 13499 and user codes" | | `ISOChannelName` | "ISO channel name" | | `ISOCode` | "ISO (13499) code" | | `ISOOnly` | "ISO 13499 only" | | `ModifyGlobalRangeCAC` | "Modify global range CAC" | | `Not_Applicable` | "N/A" | | `Of` | " of " | | `Order` | "Order" | | `Parameters_Analog` | "Analog" | | `Parameters_CAN` | "CAN" | | `Parameters_DigitalIn` | "Digital in" | | `Parameters_DigitalOut` | "Digital out" | | `Parameters_Squib` | "Squib" | | `Parameters_StreamIn` | "Stream in" | | `Parameters_StreamOut` | "Stream out" | | `Parameters_Uart` | "UART" | | `PhysicalChannelsAssigned` | " physical channel(s) assigned" | | `RemoveSensor` | "Remove Sensor" | | `Sensor` | "Sensor (SN)" | | `DallasId` | "Dallas ID" | | `AssignedBySensorId` | "(Assigned by ID)" | | `btnApplyGlobalRangeCAC` | "Apply" | | `ChannelDelete_Tooltip` | "To delete a channel, please contact an Administrator" | | `Table_NA` | "---" | | `Test` | "test" | | `TestChannelsGroupName` | "Test channels" | | `UserChannelName` | "User channel name" | | `UserCode` | "User code" | | `UserCodeOnly` | "User codes only" | --- ## 3. Invariants 1. **TranslateExtension key requirement**: The `_key` field is set via constructor and is `readonly`. It cannot be changed after instantiation. 2. **Missing resource handling**: `ProvideValue` will never return null. It returns either: - The localized string from resources - `#stringnotfound#` (if key is null/empty) - `#stringnotfound# {key}` (if key exists but no matching resource) 3. **StringResources visibility**: The `StringResources` class is `internal` and cannot be accessed outside the `GroupChannelList.Resources` namespace. 4. **ResourceManager singleton pattern**: The `ResourceManager` property uses lazy initialization with a null-check pattern; once initialized, the same instance is returned on subsequent calls. 5. **Auto-generated code constraint**: `StringResources.Designer.cs` is auto-generated by `System.Resources.Tools.StronglyTypedResourceBuilder` version 17.0.0.0. Manual changes will be overwritten on regeneration. --- ## 4. Dependencies ### This module depends on: - `System` (core .NET framework) - `System.Windows.Markup` (for `MarkupExtension` and `MarkupExtensionReturnTypeAttribute`) — WPF-specific - `System.Resources` (for `ResourceManager`) - `System.Globalization` (for `CultureInfo`) - `System.CodeDom.Compiler`, `System.Diagnostics`, `System.Runtime.CompilerServices`, `System.ComponentModel` (for generated attributes) ### What depends on this module: - **Inferred**: XAML files within the `GroupChannelList` module that use the `{local:Translate KeyName}` markup extension syntax for localized UI strings. - **Inferred**: Code-behind files that reference `StringResources` properties directly (though the class is `internal`, limiting this to within the assembly). --- ## 5. Gotchas 1. **Missing key indicator**: When a resource key is not found, the returned string includes the key name appended (e.g., `#stringnotfound# MyMissingKey`). This is useful for debugging but may appear in production UI if resources are missing. 2. **Null/empty key handling**: Passing `null` or empty string to `TranslateExtension` constructor returns only `#stringnotfound#` without a key suffix, making it impossible to distinguish which empty/null key caused the issue. 3. **Auto-generated file warning**: `StringResources.Designer.cs` is regenerated from a `.resx` file. Developers should not edit this file directly; instead, modify the underlying `.resx` file and regenerate. 4. **Culture not explicitly set**: The `TranslateExtension.ProvideValue` method does not explicitly pass a `CultureInfo` to `GetString()`. It relies on `StringResources.ResourceManager.GetString(key)` which uses the current UI culture. If `StringResources.Culture` is set, it must be done separately; the markup extension does not interact with it. 5. **Internal visibility limitation**: `StringResources` is `internal`, meaning direct programmatic access to resource strings is restricted to within the `GroupChannelList.Resources` namespace/assembly. External consumers must use `TranslateExtension` in XAML or use reflection.