The code-first
approach let´s you specify ordinary, strongly typed Interfaces
(a.k.a typealized interfaces
) to let you just utilize familiar code artefacts when dealing with i18n.
These typealized interfaces
then get picked up by the source-generator
, which generates an implementing class that then can be used f.e. in conjuntion with ordinary dependency-injection
.
This way, devlepors do not need to leave their natural habitat (the code-editor), which comes with the benefit of automatic code-refactorings, ultimatley optimizing the inner-loop, even during i18n-tasks.
The consuming target project should at least reference a suitable version of Microsoft.Extensions.Localization.Abstractions
-
install TypealizR via
-
install TypealizR.CodeFirst.Abstractions via
-
Author a
Typealized-Interface
which basically is just an ordinaryinterface
, marked withCodeFirstTypealizedAttribute
somewhere within your project.using TypealizR.CodeFirst.Abstractions; namespace Sample; [CodeFirstTypealized] // <-- this marks the interface as `to-be-typealized` public interface ILocalizables { }
-
Use properties for plain
translatables
.using TypealizR.CodeFirst.Abstractions; namespace Sample; [CodeFirstTypealized] public interface ILocalizables { LocalizedString Hello { get; } // <-- simple translatables }
return-type needs to be
LocalizedString
the generated code uses the property nameHello
as the default-value -
Use methods for type-safe translation of formatted
translatables
.using TypealizR.CodeFirst.Abstractions; namespace Sample; [CodeFirstTypealized] public interface ILocalizables { LocalizedString Greet(string userName, string planetName); // <-- formatted translatables }
return-type needs to be
LocalizedString
the generated code uses the method nameGreet
as the default-value -
setup dependency-injection in your startup-code
var services = new ServiceCollection(); services.AddLogging(); //<-- required by `Microsoft.Extensions.Localization` services.AddLocalization(); //<-- required by `Microsoft.Extensions.Localization` services.AddSingleton<ILocalizables, Localizables>(); // <-- `Localizables` gets generated by TypealizR var provider = services.BuildServiceProvider();
-
start using the generated implementation
var codeFirst = provider.GetRequiredService<IStrings>(); Console.WriteLine(codeFirst.Hello); // Hello Console.WriteLine(codeFirst.Greet("Arthur", "🌍 earth")); // Greet Arthur 🌍 earth
-
Utilize structured xml comments to provide custom default-values
using Microsoft.Extensions.Localization; using TypealizR.CodeFirst.Abstractions; namespace ConsoleSTS.CodeFirst; [CodeFirstTypealized] public interface ILocalizables { /// <summary> /// Hello, fellow developer! /// </summary> public LocalizedString Hello { get; } /// <summary> /// Hey <paramref name="userName"/>, welcome to <paramref name="planetName"/> 👍! /// </summary> public LocalizedString Greet(string userName, string planetName); }
var codeFirst = provider.GetRequiredService<IStrings>(); Console.WriteLine(codeFirst.Hello); // Hello, fellow developer! Console.WriteLine(codeFirst.Greet("Arthur", "🌍 earth")); // Hey Arthur, welcome to 🌍 earth 👍!
-
-
install TypealizR.CLI (as local or global tool) via
-
run it on your project
dotnet tr code-first export some/path/to/a.csproj
, or alternativelydotnet tr cf ex some/path/to/a.csproj
This will extract the following
resx
-file for above sample:<data name="Hello"> <value>Hello, fellow developer!</value> </data> <data name="Greet"> <value>Hey {0}, welcome to {1} 👍!</value> </data>
executing this will OVERWRITE any existing file at the moment. In the future, TypealizR will be aware of existing files and provide a way to synchronize code with those files, in order to not loose any customizations done within them. Follow the discussion and let´s define together, what workflows would be needed to make code-first-i18n a real game-changer in the future!