92 lines
6.5 KiB
Markdown
92 lines
6.5 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/Resources/TranslateExtension.cs
|
||
|
|
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/Resources/StringResources.Designer.cs
|
||
|
|
generated_at: "2026-04-16T11:12:19.064013+00:00"
|
||
|
|
model: "zai-org/GLM-5-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "b58f3ee343f377b9"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Documentation: DTS.Viewer.ViewerSettings.Resources
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
|
||
|
|
This module provides localization infrastructure for the DTS Viewer settings UI. It consists of two components: `TranslateExtension`, a WPF `MarkupExtension` that enables XAML bindings to localized strings, and `StringResources`, an auto-generated strongly-typed resource class that wraps a `.resx` file containing the actual localized string values. Together, they allow XAML markup to reference localized strings declaratively (e.g., `{local:Translate SomeKey}`) while centralizing string management through the .NET resource system.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. Public Interface
|
||
|
|
|
||
|
|
### `TranslateExtension` (public class)
|
||
|
|
|
||
|
|
**Namespace:** `DTS.Viewer.ViewerSettings`
|
||
|
|
**Base Class:** `System.Windows.Markup.MarkupExtension`
|
||
|
|
**Attribute:** `[MarkupExtensionReturnType(typeof(string))]`
|
||
|
|
|
||
|
|
| Member | Signature | Description |
|
||
|
|
|--------|-----------|-------------|
|
||
|
|
| Constructor | `TranslateExtension(string key)` | Initializes the extension with the resource key to look up. Stores the key in a readonly field `_key`. |
|
||
|
|
| `ProvideValue` | `public override object ProvideValue(IServiceProvider serviceProvider)` | Returns the localized string for `_key` from `StringResources.ResourceManager`. Returns `NotFound` constant if `_key` is null or empty. Returns `NotFound + " " + _key` if the key is not found in resources. |
|
||
|
|
|
||
|
|
**Constants:**
|
||
|
|
- `private const string NotFound = "#stringnotfound#"` — Fallback value returned when translation cannot be resolved.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### `StringResources` (internal class)
|
||
|
|
|
||
|
|
**Namespace:** `DTS.Viewer.ViewerSettings.Resources`
|
||
|
|
**Attributes:** `[GeneratedCode]`, `[DebuggerNonUserCode]`, `[CompilerGenerated]`
|
||
|
|
|
||
|
|
| Member | Signature | Description |
|
||
|
|
|--------|-----------|-------------|
|
||
|
|
| `ResourceManager` | `internal static global::System.Resources.ResourceManager ResourceManager { get; }` | Lazily-initialized, cached `ResourceManager` instance for the `DTS.Viewer.ViewerSettings.Resources.StringResources` resource bundle. |
|
||
|
|
| `Culture` | `internal static global::System.Globalization.CultureInfo Culture { get; set; }` | Overrides the current thread's `CurrentUICulture` for resource lookups via this class. Can be set to change localization at runtime. |
|
||
|
|
| `CalibrationBehavior_LinearIfAvailable` | `internal static string CalibrationBehavior_LinearIfAvailable { get; }` | Localized string: "Use the linear sensitivity, if available." |
|
||
|
|
| `CalibrationBehavior_NonLinearIfAvailable` | `internal static string CalibrationBehavior_NonLinearIfAvailable { get; }` | Localized string: "Use the non-linear sensitivity, if available." |
|
||
|
|
| `CalibrationBehavior_UseBothIfAvailable` | `internal static string CalibrationBehavior_UseBothIfAvailable { get; }` | Localized string: "Use both sensitivities, if available, as separate channels." |
|
||
|
|
| `CalibrationBehaviorText` | `internal static string CalibrationBehaviorText { get; }` | Localized string: "Calibration Behavior". |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Invariants
|
||
|
|
|
||
|
|
1. **Key immutability:** `_key` in `TranslateExtension` is assigned once in the constructor and is readonly; it cannot be changed after instantiation.
|
||
|
|
|
||
|
|
2. **Non-null return guarantee:** `TranslateExtension.ProvideValue` always returns a non-null `string` — either the localized value, the `NotFound` constant, or `NotFound + " " + _key`.
|
||
|
|
|
||
|
|
3. **ResourceManager singleton pattern:** `StringResources.ResourceManager` is lazily initialized on first access and cached; subsequent accesses return the same instance.
|
||
|
|
|
||
|
|
4. **Thread-safety of ResourceManager initialization:** The getter checks for null using `object.ReferenceEquals(resourceMan, null)` before creating a new `ResourceManager`. **Note:** This pattern is not thread-safe; race conditions could result in multiple `ResourceManager` instances being created.
|
||
|
|
|
||
|
|
5. **Resource key existence:** `StringResources` property getters pass `resourceCulture` (which may be null) to `ResourceManager.GetString`, defaulting to the current thread's `CurrentUICulture` when null.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. Dependencies
|
||
|
|
|
||
|
|
### This module depends on:
|
||
|
|
- `System` — Core .NET types
|
||
|
|
- `System.Windows.Markup` — `MarkupExtension` base class and `MarkupExtensionReturnTypeAttribute`
|
||
|
|
- `System.Resources` — `ResourceManager` for resource lookup
|
||
|
|
- `System.Globalization` — `CultureInfo` for localization
|
||
|
|
- `System.CodeDom.Compiler`, `System.Diagnostics`, `System.Runtime.CompilerServices` — Attributes for generated code (auto-generated dependency)
|
||
|
|
- **External resource file:** `StringResources.resx` (implied by the designer file; not included in source but required at runtime)
|
||
|
|
|
||
|
|
### What depends on this module:
|
||
|
|
- **Cannot be determined from source alone.** The `TranslateExtension` is designed for XAML consumption within the `DTS.Viewer.ViewerSettings` namespace, but no consumers are shown in the provided files.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. Gotchas
|
||
|
|
|
||
|
|
1. **Different error formats for different failure modes:** A null/empty key returns `"#stringnotfound#"` alone, while a valid but missing key returns `"#stringnotfound# {key}"`. This distinction can be used for debugging but may cause inconsistent UI display if not handled upstream.
|
||
|
|
|
||
|
|
2. **StringResources is internal:** The class is marked `internal`, so it cannot be accessed outside the `DTS.Viewer.ViewerSettings.Resources` namespace's assembly. `TranslateExtension` works around this by accessing `StringResources.ResourceManager` directly.
|
||
|
|
|
||
|
|
3. **Auto-generated file warning:** `StringResources.Designer.cs` is tool-generated. Manual edits will be lost when the `.resx` file is modified and the designer regenerates. The actual string values live in `StringResources.resx`, which is not included in the provided source.
|
||
|
|
|
||
|
|
4. **Thread-safety concern:** The `ResourceManager` property getter uses a non-atomic null check pattern that is not thread-safe. In multi-threaded scenarios, two threads could simultaneously pass the null check and create separate `ResourceManager` instances. While likely harmless in practice (the ResourceManager itself is thread-safe), this violates the singleton intent.
|
||
|
|
|
||
|
|
5. **Culture must be set explicitly on StringResources:** Setting `Thread.CurrentUICulture` will NOT affect `StringResources` lookups if `StringResources.Culture` has been explicitly set to a non-null value. Consumers must either leave `StringResources.Culture` as null (to inherit thread culture) or set it explicitly.
|