ProTranslate favors deterministic synchronous lookup, explicit services, and generated key paths. That makes it straightforward to reason about in desktop and mobile XAML applications, but teams should still design for culture-switch cost, retained UI targets, and trimmed builds.
This page documents implemented behavior and the current caveats. Cache policy APIs, Avalonia leak coverage, and thread-culture opt-out are implemented; lookup benchmarks and broader non-Avalonia runtime automation remain hardening work.
The common runtime path is:
TranslationService enumerates the active UI culture, parent cultures, configured fallback cultures, and default culture.Format uses string.Format(CurrentCulture, value, arguments).Keep provider lookup fast and predictable. InMemoryTranslationProvider uses concurrent dictionaries. ResourceManagerTranslationProvider delegates to .NET ResourceManager. StringLocalizerTranslationProvider delegates to IStringLocalizer.
For custom providers:
GetString.LocalizedString for normal misses instead of throwing.CompositeTranslationProvider for ordered fallback instead of adding fallback logic to adapters.Culture switching raises events through ICultureService, ITranslationService, observable strings, globalization services, and adapter binding sources. Every active translated target may refresh.
Practical guidance:
CultureService treats same culture/UI culture switches as idempotent.IObservableLocalizedString instances owned by long-lived view models.The validation matrix tracks broader non-Avalonia culture-switch stress tests and retained-target assertions as hardening work.
Adapters subscribe XAML targets to binding-source changes for attached translation properties. Current implementations use weak references for attached target subscriptions and dispose subscriptions when keys are cleared or when weak targets disappear during refresh.
Memory-retention guidance:
Translation.Key when reusing controls manually outside normal framework lifecycles.Avalonia release builds include adapter memory-retention tests for disposed binding sources, observable localized strings, and attached translation targets. Full runtime retention coverage is not yet implemented for WPF, MAUI, WinUI, and Uno.
Generated constants, accessors, provider entries, and ProTranslateStrings properties are trimming-friendly because they are normal statically referenced C# members:
using ProTranslate.Generated;
string title = translations.Value_ShellTitle();
string total = translations.Format_OrdersTotal(order.Total);
For compiled binding and x:Bind, prefer the generated ProTranslateStrings CLR surface:
public ProTranslateStrings Strings { get; } = new(translations);
<TextBlock Text="{x:Bind ViewModel.Strings.AppTitle, Mode=OneWay}" />
This gives XAML compilers a strongly typed member path and avoids depending on stringly typed reflection or resource discovery for normal static keys. Use ProTranslateGeneratedTranslationProvider when JSON catalogs should be compiled into provider code instead of loaded through assembly resource enumeration.
Trimming considerations by provider:
| Provider | Trimming notes |
|---|---|
InMemoryTranslationProvider |
Data is supplied explicitly by the app. Keep catalog loading code trim-safe. |
ProTranslateGeneratedTranslationProvider |
JSON catalog values are emitted as generated code, so no runtime resource discovery is needed. |
ResourceManagerTranslationProvider |
Ensure .resx resources and satellite assemblies are preserved by the project and publish pipeline. |
StringLocalizerTranslationProvider |
Follow Microsoft.Extensions.Localization trimming guidance for the host application and resource marker types. |
| Custom providers | Avoid reflection-based discovery unless you add the required trimming annotations or descriptors. |
The source generator itself targets netstandard2.0 as a Roslyn component and runs at build time. Generated code does not add runtime reflection requirements.
Source generation uses AdditionalFiles; include only catalogs that should affect generated keys. Generated output is sorted by key and deterministic.
Recommended practices:
Strings.*.json for culture catalogs consumed by both runtime loaders and the generator.*.protranslate.keys.txt for key manifests that are independent of a concrete culture.PTSG001 and PTSG002 warnings as build issues in CI.The generator validates catalog shape and duplicate keys within a file. ProTranslate.Analyzers validates missing static keys, placeholder mismatches, resource coverage, dynamic keys, and invalid catalogs in consuming projects.
ITranslationService.Format formats with the active formatting culture:
string text = translations.Format("Orders.Total", total);
Invalid format strings report ProTranslateDiagnosticKind.FormatFailure. By default the service returns the unformatted localized value; with TranslationFormatFailureBehavior.ReportAndThrow, it rethrows the FormatException after reporting the diagnostic.
Performance guidance:
ProTranslate.Analyzers for build-time placeholder diagnostics.CultureService can apply active cultures to CultureInfo.DefaultThreadCurrentCulture, CultureInfo.DefaultThreadCurrentUICulture, Thread.CurrentThread.CurrentCulture, and Thread.CurrentThread.CurrentUICulture. That is the default because many .NET and UI APIs read ambient culture.
Applications with strict isolation requirements can opt out:
var options = new CultureServiceOptions
{
ApplyToCurrentThread = false,
ApplyToDefaultThread = false
};
StringLocalizerTranslationProvider also temporarily sets current thread culture while it queries IStringLocalizer.
Diagnostics are structured values and are part of normal reliability behavior:
MissingTranslation.ProviderFailure.FormatFailure.Diagnostic sinks should be fast and isolated. Avoid blocking I/O in IProTranslateDiagnosticSink.Report; queue to logging infrastructure when necessary. If a diagnostic sink is part of a production path, test sink failure behavior in the host application because the current sink call is direct.
For performance-sensitive or trimmed applications, validate:
dotnet publish with the same trimming/AOT settings used in release.en-US to an RTL culture such as ar-SA.x:Bind paths that consume generated accessors.Use ./build.sh for portable validation and ./build-docs.sh after documentation changes.