• Lexical
Show / Hide Table of Contents
  • Lexical.FileSystem
    • Introduction
    • Abstractions
      • IFileSystem
        • IFileSystem
        • IFileSystemBrowse
        • IFileSystemCreateDirectory
        • IFileSystemDelete
        • IFileSystemFileAttribute
        • IFileSystemMount
        • IFileSystemMove
        • IFileSystemObserve
        • IFileSystemOpen
      • IEvent
      • IEntry
      • IOption
      • IToken
    • FileSystem
    • VirtualFileSystem
    • MemoryFileSystem
    • EmbeddedFileSystem
    • HttpFileSystem
    • Decoration
    • IFileProvider
    • Utility
      • DisposeList
      • FileScanner
      • VisitTree
      • File Operation
  • Lexical.FileProvider
    • Introduction
    • Package
    • Package.Abstractions
    • Root
    • Zip
    • Dll
    • SharpCompress
    • SharpZipLib
    • FileScanner
    • Utils
  • Lexical.Localization
    • Introduction
    • Tutorial
    • Asset
      • IAsset
      • IStringAsset
    • Line
      • ILine
      • ILineFactory
      • ILineRoot
      • ILineFormat
      • ILineLogger
      • LineComparer
    • File
      • ILineReader
      • ILineWriter
      • Ini
      • Json
      • Xml
      • Resx
      • Resources
    • Miscellaneous
      • Plurality
      • ICulturePolicy
      • IStringFormat
      • Dependency Injection
    • Practices
      • Class Library
      • Class Library DI
      • Class Library DI opt.
  • Lexical.Utilities
    • Introduction
    • UnicodeString
    • FileScanner
    • Permutation
    • Tuples
    • StructList

Scan Inlined Strings

Inlining is a way to write default string values right into the code. See Inlining for more instructions how to add inlining into code.

ILine key = LineRoot.Global.Section("Section").Key("Key")
    .Inline("Success")
    .Inline("fi", "Onnistui")
    .Inline("sv", "Det funkar");

These values can be scanned into localization files, which can then be used as templates for translations to other languages. Templates are automatically updated as code evolves, saving the developer of some inessential actions. There are three ways to scan project for inlined language strings.

  1. Method A: Use MSBuild Task
  2. Method B: Use T4 Text Templating Script
  3. Method C: Use command line tool

MSBuild Task

Download Lexical.Localization.Tool.exe and add it under the root of the project folder. mstask1


Open .csproj file. This option is visible for .NET Core and Standard projects. For framework projects, edit with text editor.

mstask2


Add the following into the <Project> node.

  <UsingTask AssemblyFile="$(ProjectDir)Lexical.Localization.Tool.exe" TaskName="LocalizationScannerTask" />
  <Target Name="LocalizationScanner" AfterTargets="Build">
    <ItemGroup>
      <InputFile Include="$(TargetPath)" />
    </ItemGroup>
    <LocalizationScannerTask ScanNames="@(InputFile)" OutputNames="scanner.ini" Verbose="True" IncludePartial="True" />
  </Target>

mstask3


Rebuild the project, and the msbuild should have now updated the scanner.ini file.
The configuration can be modified to output to other formats, to split into culture specific files and to group categories differently. See OutputNames parameter.

T4 Text Templating Script

This tutorial shows how to configure T4 script to scan the project for inlined strings and to output to specific format.


Download Lexical.Localization.Tool.exe and add it into the C# project folder.


Create new text template file "scanner.ini.tt" into the C# project. Other supported file extensions are: .json.tt, .resx.tt, .xml.tt, .resources.tt.

Add .ini.tt

Paste the following snippet into the .tt file.

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="netstandard" #>
<#@ assembly name="$(ProjectDir)Lexical.Localization.Tool.exe" #>
<#@ import namespace="Lexical.Localization.Tool" #>
<#@ import namespace="Lexical.FileProvider.Package" #>
<#@ import namespace="Lexical.FileProvider.PackageLoader" #>
<#@ import namespace="Microsoft.Extensions.DependencyInjection" #>
<#@ import namespace="Microsoft.Extensions.Logging" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ output extension=".ini"#>
<#
// Dirs
string solutionDir = Host.ResolveAssemblyReference("$(SolutionDir)");
string dllFile = Host.ResolveAssemblyReference("$(TargetPath)");
string templateDir = Path.GetDirectoryName(Host.TemplateFile);
// Log file
string logFile = Path.Combine(templateDir, Path.GetFileNameWithoutExtension(Host.TemplateFile)+".log");
File.Delete(logFile);
// Extension type: "ini", "xml", "json", "resx", "resources" 
string txt = File.ReadAllText(Host.TemplateFile);
Match m = Regex.Match(txt, "output\\s*extension\\s*=\\s*\"(\\.)?([^\"]*)\"");
string extType = m.Groups[2].Success ? m.Groups[2].Value : "ini";

// Configure
IPackageLoader[] packageLoaders = new IPackageLoader[] { Dll.Singleton, Exe.Singleton, Zip.Singleton, Rar.Singleton, _7z.Singleton, Tar.Singleton, GZip.Singleton, BZip2.Singleton, Lzw.Singleton };
string[] packageExtensions = packageLoaders.GetExtensions().Select(xt=>xt.StartsWith(".")?xt.Substring(1):xt).ToArray();
ToolConfiguration configuration = new ToolConfiguration();
configuration.Loggers.Add(new LoggerConfiguration { LogLevel = "Trace", Output = logFile, Pattern = "${message}" });
ConvertJobConfiguration convertJob = new ConvertJobConfiguration();
convertJob.InlineScans.Add( new ScanConfiguration().AddPackageExtensions(packageExtensions.Where(ext => ext != "dll" && ext != "exe")).AddFilenames(dllFile) );
configuration.ConvertJobs.Add(convertJob);

// Initialize service collection
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddLocalizationTool(configuration, packageLoaders);
serviceCollection.AddSingleton<ILoggerProvider, NLogProvider>();
serviceCollection.AddSingleton<ILoggerFactory, LoggerFactory>();
StringWriter text = new StringWriter();
serviceCollection.AddSingleton<ILineWriter>(new LocalizationTextWriter(text, extType, null));

// Run
using (var services = serviceCollection.BuildServiceProvider()) ToolJob.Run(services, configuration);

// Shutdown
NLog.LogManager.Shutdown();
#>
<#= text #>



Click on the "scanner.tt" and select "Run custom tool."

run .tt



If everything went as expected, two new files are added into the project scanner.ini and scanner.ini.log.

after run



The generated file now contains the inlined strings that are read from the code. These generated language strings can now be passed to translators and then added back to the project.

For the example the output would be:

Section:Key = Success

[fi]
Section:Key = Onnistui

[sv]
Section:Key = Det funkar

Command line tool

Download Lexical.Localization.Tool.exe, and place it into project root or some where in a Path directory.

Open command-prompt, and run

cd TutorialProject
Lexical.Localization.Tool.exe -vleo -o:scanner.ini -i:*TutorialProject.dll

Log started: 22.11.2018 14.03.06
Input pattern: *.dll
Input files: 2 file(s)
C:\<path>\TutorialProject\bin\Debug\netcoreapp2.1\TutorialProject.dll
C:\<path>\TutorialProject\obj\Debug\netcoreapp2.1\TutorialProject.dll
Run scanner
1 localization line(s).
scanner.ini
stdout.ini
TutorialProject.Program:Hello = Hello World!

Flags:

  • -v for verbose.
  • -p to include partial. Used with -s flag. Use this if scanner cannot intepret the code correctly. Adds some garbage.
  • -l:<file> to log
  • -e:<file> to print errors
  • -o:<file> to set output files for localization strings.

File scanner.ini is created or updated and should now contain the lastest inlined strings from the project.

For the example the output would be:

Section:Key = Success

[fi]
Section:Key = Onnistui

[sv]
Section:Key = Det funkar
Command line tool help. (Click here) none Lexical.Localization.Tool.exe [Options] <config.xml> <config.ini> <config.json> Version: 0.10.0 Url: http://lexical.fi/Localization/Tool/ Extensions: .resx, .json, .xml, .ini, .resources Usage permitted only with Lexical.Localization software license. Options: -l Log information and errors to standard output. (opt in) -l:stdout Log information and errors to standard output. -l:stderr Log information and errors to standard error. -l:<log file> Log information and errors to file. -v Add verbosity to log messages. -e Log errors to standard error. (opt in) -e:stdout Log errors to standard output. -e:stderr Log errors to standard error. -e:<log file> Log errors to file. -h Print this help. -? Print this help. -a Attributions and class library licenses. Scan inlined keys in .dll and .exe files: -s Scan for inlined keys in "**.dll" and "**.exe". -s:<glob pattern> Scan managed .dll and .exe files for inlined keys. -p Include keys that could not be resolved completely. "_UNKNOWN_" is used as placeholder. -!s:<glob pattern> Exclude glob pattern. Input localization files: -i Input every supported file types **.ini, **.json, **.xml, ... -i:<glob pattern> Input localization file. File name must have an extension to determine its format. -i:localization.ini -i:localization.json -i:localization.xml Wildcards are supported -i:*\localization.ini Parameters can be extracted from filename. -i:{culture\}{Type}.resources -i:<glob pattern>[,<key pattern>] Second parameter after "," sets an overriding key pattern. -i:**/localization.ini,{anysection_0/}{anysection_1/}{anysection_2/}{key_0}{/key_1} -i:<glob pattern>[/<embedded pattern>][,<key>] If file pattern is managed .dll or .exe, embedded pattern can be added with "/<embedded pattern>" -i:{culture/}[assembly.]resources.dll/[assembly.][type.]{culture.}resources,[Key] -!i:<glob pattern> Exclude glob files. Output localization files: -o Prints to std output. Same as -o:stdout.ini -o:<file pattern>[,<key pattern>] Add an output file. File name must have an extension to determine its format. -o:localization.ini -o:localization.json -o:localization.xml "stdout" is special cast that outputs the the file into output pipe. -o:stdout.ini -o:stdout.json Parameters allow the output to be dispersed into multiple files. -o:{culture\}{Type}.resources Second parameter determines the format of keys -o:{culture\}{Type}.resources,{anysection_0.}{anysection_1.}{anysection_2.}{key_0}{.key_1} Pattern is a format with with key parameters: {Culture} - Matches to key.SetCulture("en") {Assembly} - Matches to key.AssemblySection(asm) {Resource} - Matches to key.ResourceSection("xx") {Type} - Matches to key.TypeSection(type) {Section} - Matches to key.Section("xx") {anysection} - Matches to assembly, type and section. {Key} - Matches to regular key key.Key("x") and key["x"] Parameter can be optional in curly braces {} and required in brackets []. [-culture] {-culture} Parameter can be added multiple times, which matches when group has identifier multiple times. "localization{-key_0}{-key_1}.ini - Matches to key.Key("x").Key("x") Before and after the pattern identifier pre- and postfix separator characters can be added: {/culture.} Test to list files -t List files within packages, for testing purposes. -t:<glob pattern> List file with glob pattern, for testing purposes. -!t:<glob pattern> Excludes list. Examples: Lexical.Localization.Tool.exe -levos:**.exe -s:**.dll Lexical.Localization.Tool.exe -levs:**.exe -s:**.dll -o:stdout.json Lexical.Localization.Tool.exe -levs:**.dll -o:localization{-culture}.ini Lexical.Localization.Tool.exe -levs:**.dll -o:stdout.ini,{culture:}{root:}{anysection_0:}{anysection_1:}{Key} Scan dlls, print .ini Lexical.Localization.Tool.exe -levos:**.dll Read assembly and satellite assemeblies for embedded resources, print .ini. Lexical.Localization.Tool.exe -o -i:**.dll/**.resources -i:**{/culture/}{Type}.resources.dll/**.resources Scan satellite assemeblies, print .ini. Verbose logs Lexical.Localization.Tool.exe -levo -i:**.dll/**.resources -i:**{/culture/}{Type}.resources.dll/**.resources

Converting files

Command line tool can be used for converting localization files from one format to another.

Lexical.Localization.Tool.exe -vle -o:localization.resx -i:localization.ini

It can also be used to merge and disperse files into a configuration.

Lexical.Localization.Tool.exe -vle -o:localization{-culture}.ini -i:{culture/}localization.resources
Lexical.Localization.Tool.exe -vle -o:localization.ini,{culture:}{anysection_0:}{anysection_1:}{anysection_n:}{key_0:}{key_n} -i:{culture/}localization.resources
Back to top Copyright © 2015-2020 Toni Kalajainen