# Cliloc Text System
**Referenced Files in This Document**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
- [Strings.resx](file://ClassicAssist.Shared/Resources/Strings.resx)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [Strings.en-AU.resx](file://ClassicAssist.Shared/Resources/Strings.en-AU.resx)
- [Strings.en-GB.resx](file://ClassicAssist.Shared/Resources/Strings.en-GB.resx)
- [Strings.it-IT.resx](file://ClassicAssist.Shared/Resources/Strings.it-IT.resx)
- [Strings.ko-KR.resx](file://ClassicAssist.Shared/Resources/Strings.ko-KR.resx)
- [Strings.pl-PL.resx](file://ClassicAssist.Shared/Resources/Strings.pl-PL.resx)
- [Strings.zh.resx](file://ClassicAssist.Shared/Resources/Strings.zh.resx)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [ClilocFilter.cs](file://ClassicAssist.Shared/Data/Filters/ClilocFilter.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
- [ClilocSelectionWindow.xaml](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml)
- [ClilocSelectionWindow.xaml.cs](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml.cs)
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
10. [Appendices](#appendices)
## Introduction
This document explains the cliloc text system and localization framework used by ClassicAssist.Avalonia. It covers how localized strings are loaded from Ultima Online client files, how .resx-based resources are structured and consumed at runtime, how XAML bindings resolve strings via a value converter, and how multi-language support is implemented with detection, fallback, and runtime switching. It also documents integration with game text formatting (parameter substitution), strategies for adding new languages, maintaining consistency, and performance considerations for large text databases.
## Project Structure
The cliloc and localization features span shared data models, resource files, UI converters, and view models:
- UO data layer provides the core cliloc loader/parser and language enumeration.
- Shared resources provide .resx-based application strings with designer-generated accessors.
- Avalonia UI provides a StringToResourceConverter to bind XAML to localized strings.
- Autoloot feature includes a window and view model that interact with cliloc entries.
```mermaid
graph TB
subgraph "Shared"
CL["Cliloc.cs"]
LG["Language.cs"]
RESX["Strings.*.resx + Strings.Designer.cs"]
CF["ClilocFilter.cs"]
CVM["ClilocSelectionViewModel.cs"]
end
subgraph "Avalonia UI"
SRC["StringToResourceConverter.cs"]
CSW["ClilocSelectionWindow.xaml(.cs)"]
end
CL --> LG
RESX --> SRC
SRC --> CSW
CF --> CL
CVM --> CL
```
**Diagram sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [ClilocFilter.cs](file://ClassicAssist.Shared/Data/Filters/ClilocFilter.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
- [ClilocSelectionWindow.xaml.cs](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml.cs)
**Section sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [ClilocFilter.cs](file://ClassicAssist.Shared/Data/Filters/ClilocFilter.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
- [ClilocSelectionWindow.xaml.cs](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml.cs)
## Core Components
- Cliloc class: Loads, parses, and manages cliloc entries from Ultima Online client files. Provides lookup APIs for retrieving localized strings by ID, with optional parameter substitution.
- Language enum: Represents supported cultures/languages and drives selection and fallback behavior.
- .resx resources: Provide application-level localized strings with designer-generated strongly-typed accessors.
- StringToResourceConverter: Bridges XAML binding to .resx resources, enabling dynamic string resolution and parameter substitution in markup.
- ClilocFilter and ClilocSelectionViewModel: Use cliloc data for filtering and user selection workflows.
Key responsibilities:
- Resource discovery and parsing for cliloc files.
- In-memory indexing for fast lookups.
- Culture-aware resolution and fallback.
- Parameterized message formatting compatible with UO cliloc format.
- Integration points for UI and filters.
**Section sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [ClilocFilter.cs](file://ClassicAssist.Shared/Data/Filters/ClilocFilter.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
## Architecture Overview
The system combines two complementary localization mechanisms:
- Game cliloc: Loaded from UO client files into an in-memory store for fast retrieval and formatting.
- Application .resx: Designer-managed resources for UI strings, accessed via generated properties and XAML converters.
```mermaid
sequenceDiagram
participant UI as "XAML View"
participant Conv as "StringToResourceConverter"
participant Res as ".resx Resources"
participant VM as "ViewModel"
participant CL as "Cliloc"
participant Lang as "Language"
UI->>Conv : Resolve key with parameters
Conv->>Res : Get localized string by key/culture
Res-->>Conv : Base string template
Conv->>Conv : Apply parameter substitution
Conv-->>UI : Formatted text
VM->>CL : Lookup(clilocId, params)
CL->>Lang : Determine current culture/fallback
CL-->>VM : Localized message
```
**Diagram sources**
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
## Detailed Component Analysis
### Cliloc Class
Responsibilities:
- Discover and load cliloc files from the UO client directory.
- Parse binary or text-based cliloc formats into an internal index keyed by numeric IDs.
- Provide methods to retrieve messages by ID, optionally substituting parameters using UO-style placeholders.
- Integrate with Language to select appropriate locale when multiple locales exist.
Data structures and complexity:
- Primary storage: Dictionary-like mapping from cliloc ID to message template.
- Lookup time: O(1) average for direct ID access.
- Substitution: Linear in number of parameters; uses efficient string building.
Error handling:
- Missing files or corrupted entries are handled gracefully with logging and fallback to default language or base templates.
- Invalid parameter counts produce safe formatted output rather than exceptions.
Optimization opportunities:
- Pre-warm caches on startup for frequently used IDs.
- Lazy-load large cliloc partitions if needed.
- Avoid repeated allocations by reusing buffers for parameter substitution.
Integration points:
- Consumed by filters and view models for displaying contextual messages.
- Uses Language to determine effective culture and fallback chain.
```mermaid
classDiagram
class Cliloc {
+Load(clientPath)
+Get(id, params) string
+Contains(id) bool
-index Map
-culture string
}
class Language {
+CurrentCulture string
+FallbackChain() IEnumerable
+SelectBest(candidates) string
}
Cliloc --> Language : "uses"
```
**Diagram sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
**Section sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
### .resx Resource System and Designer Code Generation
Structure:
- Default resource file: Strings.resx
- Cultured variants: Strings.en-AU.resx, Strings.en-GB.resx, Strings.it-IT.resx, Strings.ko-KR.resx, Strings.pl-PL.resx, Strings.zh.resx
- Designer code: Strings.Designer.cs exposes strongly typed properties for each key, bound to the active culture.
Runtime behavior:
- The ResourceManager selects the best matching resource based on CurrentUICulture and falls back to the neutral resource if a specific culture is missing.
- Designer-generated properties encapsulate culture selection and null safety.
Consistency and maintenance:
- Keep keys aligned across all .resx files to avoid missing translations.
- Use consistent naming conventions and include comments in .resx for translators.
```mermaid
flowchart TD
Start(["Access property via Strings.Designer"]) --> CheckCulture["Resolve CurrentUICulture"]
CheckCulture --> FindResource["Find matching .resx"]
FindResource --> Found{"Found?"}
Found --> |Yes| ReturnVal["Return localized string"]
Found --> |No| Fallback["Fallback to neutral Strings.resx"]
Fallback --> ReturnVal
```
**Diagram sources**
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [Strings.resx](file://ClassicAssist.Shared/Resources/Strings.resx)
- [Strings.en-AU.resx](file://ClassicAssist.Shared/Resources/Strings.en-AU.resx)
- [Strings.en-GB.resx](file://ClassicAssist.Shared/Resources/Strings.en-GB.resx)
- [Strings.it-IT.resx](file://ClassicAssist.Shared/Resources/Strings.it-IT.resx)
- [Strings.ko-KR.resx](file://ClassicAssist.Shared/Resources/Strings.ko-KR.resx)
- [Strings.pl-PL.resx](file://ClassicAssist.Shared/Resources/Strings.pl-PL.resx)
- [Strings.zh.resx](file://ClassicAssist.Shared/Resources/Strings.zh.resx)
**Section sources**
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [Strings.resx](file://ClassicAssist.Shared/Resources/Strings.resx)
- [Strings.en-AU.resx](file://ClassicAssist.Shared/Resources/Strings.en-AU.resx)
- [Strings.en-GB.resx](file://ClassicAssist.Shared/Resources/Strings.en-GB.resx)
- [Strings.it-IT.resx](file://ClassicAssist.Shared/Resources/Strings.it-IT.resx)
- [Strings.ko-KR.resx](file://ClassicAssist.Shared/Resources/Strings.ko-KR.resx)
- [Strings.pl-PL.resx](file://ClassicAssist.Shared/Resources/Strings.pl-PL.resx)
- [Strings.zh.resx](file://ClassicAssist.Shared/Resources/Strings.zh.resx)
### StringToResourceConverter for XAML Binding
Purpose:
- Enables XAML bindings to resolve localized strings directly in markup.
- Supports passing parameters for dynamic substitution within resource templates.
Behavior:
- Reads the bound key and optional parameters.
- Uses the .resx resource manager to fetch the template for the current culture.
- Applies parameter substitution before returning the final string.
Usage patterns:
- Bind Text properties to keys defined in .resx.
- Pass additional context via ConverterParameter or MultiBinding to enrich messages.
```mermaid
sequenceDiagram
participant Xaml as "XAML Binding"
participant Conv as "StringToResourceConverter"
participant RM as "ResourceManager"
Xaml->>Conv : Convert(key, parameters)
Conv->>RM : GetString(key, culture)
RM-->>Conv : Template
Conv->>Conv : Substitute parameters
Conv-->>Xaml : Final string
```
**Diagram sources**
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
**Section sources**
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
### Multi-Language Support: Detection, Fallback, and Runtime Switching
Detection:
- Uses the system’s CurrentUICulture to pick the best available resource set.
- Falls back to neutral resources when a specific culture is not present.
Fallback mechanism:
- If a culture-specific .resx is missing, the system automatically resolves to the default Strings.resx.
- For cliloc, similar fallback logic applies when a particular locale entry is unavailable.
Runtime switching:
- Changing CurrentUICulture triggers re-resolution of resources.
- UI components using StringToResourceConverter will update dynamically when culture changes.
```mermaid
stateDiagram-v2
[*] --> Initialized
Initialized --> DetectCulture : "On startup"
DetectCulture --> Active : "Culture resolved"
Active --> Switching : "User changes language"
Switching --> Active : "New culture applied"
```
**Diagram sources**
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
**Section sources**
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
### Integration with Game Text Formatting and Parameter Substitution
Game cliloc format:
- Messages may contain placeholders for parameters (e.g., names, numbers).
- The Cliloc class substitutes these parameters safely, preserving formatting and handling missing values.
Application resources:
- .resx templates can also accept parameters via the converter, allowing flexible UI messages.
Consistency:
- Maintain parallel parameter sets between cliloc and .resx where applicable to ensure consistent UX across game and UI text.
```mermaid
flowchart TD
Entry(["Lookup request"]) --> GetTemplate["Fetch template"]
GetTemplate --> HasParams{"Parameters provided?"}
HasParams --> |No| ReturnTemplate["Return template as-is"]
HasParams --> |Yes| Validate["Validate count/types"]
Validate --> Format["Format with placeholders"]
Format --> ReturnFormatted["Return formatted string"]
```
**Diagram sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
**Section sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
### Adding New Languages and Maintaining Consistency
Steps to add a new language:
- Create a new .resx file named with the target culture (e.g., Strings.fr-FR.resx).
- Copy keys from the default Strings.resx and translate values.
- Ensure all keys are present to avoid fallback surprises.
- Update any UI elements that expose language choices to include the new culture.
Translating existing strings:
- Use the .resx editor to maintain translation quality and consistency.
- Keep comments in .resx to guide translators.
Maintaining consistency:
- Regularly compare new keys added to Strings.resx against existing culture files.
- Implement checks or CI tasks to detect missing translations.
**Section sources**
- [Strings.resx](file://ClassicAssist.Shared/Resources/Strings.resx)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
### Autoloot Integration with Cliloc
Components:
- ClilocFilter: Filters chat or journal entries using cliloc IDs and patterns.
- ClilocSelectionViewModel: Manages selection and display of cliloc entries for autoloot rules.
- ClilocSelectionWindow: Presents the selection UI, leveraging StringToResourceConverter for labels and messages.
Workflow:
- User opens the selection window.
- ViewModel queries Cliloc for relevant entries.
- UI binds to localized strings via the converter for labels and descriptions.
```mermaid
sequenceDiagram
participant User as "User"
participant Win as "ClilocSelectionWindow"
participant VM as "ClilocSelectionViewModel"
participant CL as "Cliloc"
participant Conv as "StringToResourceConverter"
User->>Win : Open window
Win->>VM : Initialize
VM->>CL : Load/filter cliloc entries
CL-->>VM : Entries
Win->>Conv : Bind labels/messages
Conv-->>Win : Localized text
Win-->>User : Display selection UI
```
**Diagram sources**
- [ClilocSelectionWindow.xaml.cs](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
**Section sources**
- [ClilocFilter.cs](file://ClassicAssist.Shared/Data/Filters/ClilocFilter.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
- [ClilocSelectionWindow.xaml.cs](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml.cs)
## Dependency Analysis
Relationships among core components:
- Cliloc depends on Language for culture selection and fallback.
- StringToResourceConverter depends on .resx resources and the active culture.
- UI components depend on both Cliloc (for game text) and StringToResourceConverter (for UI text).
```mermaid
graph TB
CL["Cliloc.cs"] --> LG["Language.cs"]
SRC["StringToResourceConverter.cs"] --> RESX["Strings.Designer.cs"]
CVM["ClilocSelectionViewModel.cs"] --> CL
CSW["ClilocSelectionWindow.xaml.cs"] --> SRC
CF["ClilocFilter.cs"] --> CL
```
**Diagram sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
- [ClilocSelectionWindow.xaml.cs](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml.cs)
- [ClilocFilter.cs](file://ClassicAssist.Shared/Data/Filters/ClilocFilter.cs)
**Section sources**
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
- [Language.cs](file://ClassicAssist.Shared/Data/Language.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [ClilocSelectionViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/Autoloot/ClilocSelectionViewModel.cs)
- [ClilocSelectionWindow.xaml.cs](file://ClassicAssist.Avalonia/Views/Autoloot/ClilocSelectionWindow.xaml.cs)
- [ClilocFilter.cs](file://ClassicAssist.Shared/Data/Filters/ClilocFilter.cs)
## Performance Considerations
- Large cliloc datasets:
- Prefer dictionary-backed lookups for O(1) access.
- Cache frequently used IDs to reduce parsing overhead.
- Consider lazy-loading partitions if memory usage becomes a concern.
- Parameter substitution:
- Reuse formatters/buffers to minimize allocations.
- Validate parameter counts early to avoid expensive formatting paths.
- .resx access:
- ResourceManager is efficient; avoid repeated culture switches in tight loops.
- Batch UI updates to reduce rebind churn.
- UI responsiveness:
- Offload heavy cliloc operations to background threads and marshal results to UI thread.
- Debounce rapid language switches to prevent excessive re-resolution.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- Missing translations:
- Verify that culture-specific .resx files contain all keys present in the default Strings.resx.
- Check CurrentUICulture settings during runtime to ensure expected culture is active.
- Incorrect parameter substitution:
- Confirm placeholder positions match parameter order.
- Log template and parameters to diagnose mismatches.
- Cliloc lookup failures:
- Ensure cliloc files are present and readable.
- Validate IDs and handle missing entries with fallback messages.
- UI not updating after language change:
- Ensure bindings use StringToResourceConverter and that culture change triggers re-evaluation.
**Section sources**
- [Strings.Designer.cs](file://ClassicAssist.Shared/Resources/Strings.Designer.cs)
- [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs)
- [Cliloc.cs](file://ClassicAssist.Shared/UO/Data/Cliloc.cs)
## Conclusion
The cliloc text system and localization framework in ClassicAssist.Avalonia combine robust game text loading (.resx-based application resources) with efficient in-memory management for UO cliloc files. The architecture supports multi-language environments with reliable fallback, dynamic parameter substitution, and seamless XAML integration. By following the guidelines for adding languages, maintaining consistency, and optimizing performance, teams can deliver a responsive, localized experience across diverse locales.
[No sources needed since this section summarizes without analyzing specific files]
## Appendices
- Best practices:
- Centralize key definitions and enforce parity across cultures.
- Use descriptive comments in .resx for translators.
- Test parameter substitution thoroughly with edge cases.
- References:
- See component files for implementation details and integration points.
[No sources needed since this section provides general guidance]