Skip to content

Latest commit

 

History

History
102 lines (76 loc) · 4.56 KB

File metadata and controls

102 lines (76 loc) · 4.56 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build Commands

dotnet build                              # Build all projects
dotnet test                               # Run all tests
dotnet test --filter "FullyQualifiedName~TestName"  # Run single test
dotnet clean                              # Clean build artifacts

Architecture

This is a .NET translation library solution. Build outputs go to .artifacts/ (not per-project bin/obj).

Naming Convention

Projects automatically get Deck.Dev. prefix for namespace and assembly:

  • Project: Translation.Abstractions
  • Namespace: Deck.Dev.Translation.Abstractions
  • Assembly: Deck.Dev.Translation.Abstractions.dll

Build Configuration

  • Directory.Build.props: Shared properties (namespace/assembly naming, language settings)
  • Directory.Packages.props: Central Package Management - all package versions defined here
  • Default target: net8.0 (override per-project if needed, e.g., netstandard2.0)

Compiler Settings

  • TreatWarningsAsErrors: enabled
  • Nullable: enabled (uses polyfill for netstandard2.0)
  • ImplicitUsings: disabled - explicit using statements required

Projects

Project TFM Purpose
Translation.Abstractions netstandard2.0 Core types: TranslationString, ITranslationProvider, ITranslationProviderFactory
Translation.Generator netstandard2.0 Roslyn incremental source generator — reads .lockeys files, emits typed C#
Translation.Runtime net8.0 TemplateEngine (no-boxing formatter), JsonTranslationProvider, LocalizationContext
Translation.Demo.Wpf net8.0-windows10.0.19041 WPF demo app with ReactiveUI, CommunityToolkit.Mvvm, DI
Translation.Tests net8.0 xunit + FluentAssertions tests for parser, engine, and integration

Translation System Design

File format: .lockeys (INI-inspired, typed placeholders)

# Comment
[SectionName]
Key : Fallback text with {paramName|Type} or {paramName:formatString|Type} or {paramName}

Type hierarchy (no-boxing design):

  • TranslationString (abstract) — base type with Key, Resolve(), implicit string conversion
  • LiteralTranslationString — for keys without parameters
  • Generated file-scoped classes — per parameterized key, stores typed fields (no boxing)

Source generator: Reads .lockeys from AdditionalFiles, generates a static class per file (filename = class name) with nested classes per [Section]. Properties for literal keys, methods for parameterized keys.

Runtime resolution: ITranslationProvider.TryGetTemplate(key, out template). Templates use named placeholders ({paramName} or {paramName:format}). TemplateEngine.Replace<T> is generic to avoid boxing. TemplateEngine.Unescape handles {{/}} escaping.

Consuming project setup:

<ProjectReference Include="Translation.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="Translation.Abstractions.csproj" />
<ProjectReference Include="Translation.Runtime.csproj" />
<AdditionalFiles Include="Translations\*.lockeys" />

Key Implementation Details

  • Placeholders without a type ({param}) default to object
  • Supported types include object and TimeSpan in addition to primitives and date/time types
  • Generator project needs InternalsVisibleTo for test project to access parser types
  • string and object do NOT implement IFormattableTemplateEngine has separate Replace overloads for each
  • Source generators must target netstandard2.0; the Generator uses IsExternalInit polyfill for records and EquatableArray<T> for correct incremental caching
  • Machine may use non-English locale — tests with formatted numbers/currencies should use CultureScope(CultureInfo.InvariantCulture)
  • TemplateEngine.Replace preserves {{/}}; TemplateEngine.Unescape converts them as final step
  • Sequential Replace calls for multi-param templates (single-pass TemplateWriter ref struct is a future optimization)

Documentation

Full docs are in the docs/ folder:

Adding Packages

Use Central Package Management. In project file:

<PackageReference Include="PackageName" />  <!-- No version -->

Add version to Directory.Packages.props:

<PackageVersion Include="PackageName" Version="x.x.x" />