This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
dotnet build # Build all projects
dotnet test # Run all tests
dotnet test --filter "FullyQualifiedName~TestName" # Run single test
dotnet clean # Clean build artifactsThis is a .NET translation library solution. Build outputs go to .artifacts/ (not per-project bin/obj).
Projects automatically get Deck.Dev. prefix for namespace and assembly:
- Project:
Translation.Abstractions - Namespace:
Deck.Dev.Translation.Abstractions - Assembly:
Deck.Dev.Translation.Abstractions.dll
- 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)
TreatWarningsAsErrors: enabledNullable: enabled (uses polyfill for netstandard2.0)ImplicitUsings: disabled - explicit using statements required
| 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 |
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 withKey,Resolve(), implicitstringconversionLiteralTranslationString— 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" />- Placeholders without a type (
{param}) default toobject - Supported types include
objectandTimeSpanin addition to primitives and date/time types - Generator project needs
InternalsVisibleTofor test project to access parser types stringandobjectdo NOT implementIFormattable—TemplateEnginehas separateReplaceoverloads for each- Source generators must target netstandard2.0; the Generator uses
IsExternalInitpolyfill for records andEquatableArray<T>for correct incremental caching - Machine may use non-English locale — tests with formatted numbers/currencies should use
CultureScope(CultureInfo.InvariantCulture) TemplateEngine.Replacepreserves{{/}};TemplateEngine.Unescapeconverts them as final step- Sequential
Replacecalls for multi-param templates (single-passTemplateWriterref struct is a future optimization)
Full docs are in the docs/ folder:
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" />