C#6.0 string interpolation localization

前端 未结 9 1127
感情败类
感情败类 2020-11-29 04:59

C#6.0 have a string interpolation - a nice feature to format strings like:

 var name = \"John\";
 WriteLine($\"My name is {name}\");

The ex

相关标签:
9条回答
  • 2020-11-29 05:35

    The C# 6.0 string interpolation won't help you if the format string is not in your C# source code. In that case, you will have to use some other solution, like this library.

    0 讨论(0)
  • 2020-11-29 05:43

    Using the Microsoft.CodeAnalysis.CSharp.Scripting package you can achieve this.

    You will need to create an object to store the data in, below a dynamic object is used. You could also create an specific class with all the properties required. The reason to wrap the dynamic object in a class in described here.

    public class DynamicData
    {
        public dynamic Data { get; } = new ExpandoObject();
    }
    

    You can then use it as shown below.

    var options = ScriptOptions.Default
        .AddReferences(
            typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).GetTypeInfo().Assembly,
            typeof(System.Runtime.CompilerServices.DynamicAttribute).GetTypeInfo().Assembly);
    
    var globals = new DynamicData();
    globals.Data.Name = "John";
    globals.Data.MiddleName = "James";
    globals.Data.Surname = "Jamison";
    
    var text = "My name is {Data.Name} {Data.MiddleName} {Data.Surname}";
    var result = await CSharpScript.EvaluateAsync<string>($"$\"{text}\"", options, globals);
    

    This is compiling the snippet of code and executing it, so it is true C# string interpolation. Though you will have to take into account the performance of this as it is actually compiling and executing your code at runtime. To get around this performance hit if you could use CSharpScript.Create to compile and cache the code.

    0 讨论(0)
  • 2020-11-29 05:47

    If we use interpolation then we are thinking in terms of methods, not constants. In that case we could define our translations as methods:

    public abstract class InterpolatedText
    {
        public abstract string GreetingWithName(string firstName, string lastName);
    }
    
    public class InterpolatedTextEnglish : InterpolatedText
    {
        public override string GreetingWithName(string firstName, string lastName) =>
            $"Hello, my name is {firstName} {lastName}.";
    }
    

    We can then load an implementation of InterpolatedText for a specific culture. This also provides a way to implement fallback, as one implementation can inherit from another. If English is the default language and other implementations inherit from it, there will at least be something to display until a translation is provided.

    This seems a bit unorthodox, but offers some benefits:

    Primarily, the string used for interpolation is always stored in a strongly-typed method with clearly-specified arguments.

    Given this: "Hello, my name is {0} {1}" can we determine that the placeholders represent first name and last name in that order? There will always be a method which matches values to placeholders, but there's less room for confusion when the interpolated string is stored with its arguments.

    Similarly, if we store our translation strings in one place and use them in another, it becomes possible to modify them in a way that breaks the code using them. We can add {2} to a string which will be used elsewhere, and that code will fail at runtime.

    Using string interpolation this is impossible. If our translation string doesn't match the available arguments it won't even compile.


    There are drawbacks, although I see difficulty in maintaining any solution.

    The greatest is portability. If your translation is coded in C# and you switch, it's not the easiest thing to export all of your translations.

    It also means that if you wish to farm out translations to different individuals (unless you have one person who speaks everything) then the translators must modify code. It's easy code, but code nonetheless.

    0 讨论(0)
提交回复
热议问题