command-line-api icon indicating copy to clipboard operation
command-line-api copied to clipboard

Add Localization Features package for System.CommandLine

Open fredrikhr opened this issue 5 years ago • 2 comments

TL;DR

  • Adds a new package System.CommandLine.Localization that contains functionality that extends System.CommandLine with localization features.
  • Adds a LocalizedHelpBuilder type that derives from the default HelpBuilder, but offers localized help output.
  • Adds a UseLocalization extension method on CommandLineBuilder.

Details

The new System.CommandLine.Localization package uses the Microsoft.Extensions.Localization package to provide localization features. By default the implementation uses the Resource Manager based IStringLocalizerFactory which provides localization from embedded resources that are compiled from .resx files at compile time. ref.: Globalization and Localization in ASP.NET Core

UseLocalization extension method

New API

namespace System.CommandLine.Builder
{
    partial class CommandLineBuilderExtensions
    {
        public partial static CommandLineBuilder UseLocalization(
            this CommandLineBuilder builder, Type? resourceSource = null);
    }
}

The UseLocalization extension method is the main entry point that makes the CommandLine application localization aware. In essence it does two things:

  1. It add a IStringLocalizerFactory to the BindingContext of the invocation.
  2. Calls UseHelpBuilder to setup the new LocalizedHelpBuilder that outputs help using the string localizer factory mentioned above.

The optional Type argument is used to specify from which assembly and resource file the strings are localized. If the Type is not specified, the Type that declares the entry point (i.e. the Main method) in the entry assembly is used.

If the Generic Host integration (System.CommandLine.Hosting) is being used and the binding context knows how to resolve an IHost instance, the extension method attempt to resolve the IStringLocalizerFactory from the service provider of the Generic Host. This will respect any configuration made in the Host setup with regards to logging and localization options. The reference to IHost is made via reflection, so that System.CommandLine.Localization does not need to depend on the Generic Host package.

LocalizedHelpBuilder class

New Type

using System.CommandLine.Help;

// New Namespace
namespace System.CommandLine.Localization
{
    public partial class LocalizedHelpBuilder : HelpBuilder
    {
        public LocalizedHelpBuilder(IStringLocalizerFactory localizerFactory,
            Type resourceSource, IConsole console, int? columnGutter = null,
            int? indentationSize = null, int? maxWidth = null)
        { }
    }
}

The LocalizedHelpBuilder class derives from the System.CommandLine help builder and uses its base implementation as much as possible. In order to localize the output of the static strings in the DefaultHelpText class (and some constant literals in HelpBuilder, System.Command.Localization also adds a LocalizedHelpBuilder.resx resource file that together with the XLF files provides localized strings for the Help output.

In order to localize the actual help on commands, options and arguments, the Localized Help Builder walks the command or option that it is writing output for and clones all symbols (effectively making localized clones). The Localized Help Builder then replaces the Description of each symbol with a localized description.

fredrikhr avatar Aug 06 '20 08:08 fredrikhr

I don't think xlf is generated by Arcade. We need to do that so it can fit into existing localization system.

But that's also a headache, we would require the contributor to run a build with arcade (which is disabled in "dev mode") and then checkin the new xlfs. Maybe the "right way" is we could have a bot to run and append a checkin for PRs touching resx files.

wli3 avatar Aug 20 '20 22:08 wli3

Related: #1125

jonsequitur avatar Dec 11 '20 20:12 jonsequitur