• 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

Localization Writer

Lexical.Localization.Plus class library contains writer classes, extension methods and source codes for file formats .ini, .xml, .json, .resx, and .resources.

Format Writer
.ini IniLinesWriter
.json JsonLinesWriter
.xml XmlLinesWriter
.resx ResxLinesWriter
.resources ResourcesLinesWriter

Writer classes inherit their respecctive reader classes, and thus have reader features as well.

LineWriterMap is a dictionary that contains default writer classes.

ILineFileFormat format = LineWriterMap.Default["ini"];

Writers can also be acquired from the singleton instances.

ILineFileFormat format = IniLinesWriter.Default;

Writing Lines

If file format can be inferred from file extension, then content can be written with LineWriterMap.

.WriteLines() writes IEnumerable<ILine> lines to a file.

IEnumerable<ILine> lines = new List<ILine>
{
    LineAppender.NonResolving.Culture("en").Type("Class").Key("Hello").Format("Hello World!")
};
LineWriterMap.Default.WriteLines(
    lines,
    srcFilename: null,
    dstFilename: "localization1.ini",
    lineFormat: null,
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

IniLinesWriter writes lines as .ini file format.

IniLinesWriter.Default.WriteLines(
    lines,
    srcFilename: null,
    dstFilename: "localization1.ini",
    lineFormat: null,
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

JsonLinesWriter writes lines as .json file format.

JsonLinesWriter.Default.WriteLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.json", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

XmlLinesWriter writes lines as .xml file format.

XmlLinesWriter.Default.WriteLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.xml", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

ResxLinesWriter writes lines as .resx file format. ILineFormat is required in order to formulate key into string.

ResxLinesWriter.Default.WriteLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.resx", 
    lineFormat: LineParameterPrinter.Default, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

ResourcesLinesWriter writes lines as .resources file format.

ResourcesLinesWriter.Default.WriteLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.resources", 
    lineFormat: LineParameterPrinter.Default, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);


LinePattern can be used for formulating how lines are grouped into levels when writing to structural file format. File formats .json and .xml have a tree structure, and .ini has shallow two level structure.

// Create lines
IEnumerable<ILine> lines = new List<ILine> {
    LineAppender.NonResolving.Culture("en")
        .Section("Section1").Section("Section2").Type("Class").Key("Hello").N("Plural")
        .Format("Hello {0} worlds!")
};
// Grouping rule: Everything on one level. If culture is provided, then on its own level.
ILineFormat grouping = new LinePattern("{Section}{Type}[Key]{/Culture}");
string text = XmlLinesWriter.Default.WriteLinesAsString(
    lines,
    srcText: null,
    lineFormat: grouping,
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

"/" divides a key into levels.

// Grouping rule: Culture on first level. Each section in one level. Type, key and rest on last level.
ILineFormat grouping = new LinePattern("{Culture}/{Section}/{Type}[Key]");
string text = XmlLinesWriter.Default.WriteLinesAsString(
    lines,
    srcText: null,
    lineFormat: grouping,
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

If the separator "/" is inside a capture part, e.g. "{/Section}", then each occurance of the key part starts a new level.

ILine key = LineAppender.NonResolving.Culture("en").Section("Section1").Section("Section2").Type("Class").Key("Hello").N("Plural");
IEnumerable<ILine> lines = new List<ILine> { key.Format("Hello {0} worlds!") };
// Grouping rule: Culture on first level. Each section in own level. Type, key and rest on last level.
ILineFormat grouping = new LinePattern("{Culture}/{Section/}{Type}[Key]");
string text = XmlLinesWriter.Default.WriteLinesAsString(
    lines,
    srcText: null,
    lineFormat: grouping,
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

Writing String Key Lines

.WriteUnformedLines() writes from IEnumerable<KeyValuePair<string, IString>> lines to a file.

IEnumerable<KeyValuePair<string, IString>> lines = new Dictionary<string, IString>
{
    { "en.MyController.Hello", CSharpFormat.Default.Parse("Hello World!") }
};
ILineFormat policy = new LinePattern("{culture.}[Type.]{Key}[.Key_n]");
LineWriterMap.Default.WriteUnformedLines(
    lines,
    srcFilename: null,
    dstFilename: "localization1.ini",
    lineFormat: policy,
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

IniLinesWriter writes lines as .ini file format. ILineFormat is required to formulate key into string.

IniLinesWriter.Default.WriteUnformedLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.ini", 
    lineFormat: policy, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

JsonLinesWriter writes lines as .json file format.

JsonLinesWriter.Default.WriteUnformedLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.json", 
    lineFormat: policy, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

XmlLinesWriter writes lines as .xml file format.

XmlLinesWriter.Default.WriteUnformedLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.xml", 
    lineFormat: policy, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

ResxLinesWriter writes lines as .resx file format. ILineFormat is not used.

ResxLinesWriter.Default.WriteUnformedLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.resx", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

ResourcesLinesWriter writes lines as .resources file format.

ResourcesLinesWriter.Default.WriteUnformedLines(
    lines, 
    srcFilename: null, 
    dstFilename: "localization1.resources", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

Writing Key Tree

.WriteLineTree() writes structurally from structural ILineTree to a file.

ILineTree tree = new LineTree();
ILineTree level1 = tree.Create(LineAppender.NonResolving.Culture("en"));
ILineTree level2 = level1.Create(LineAppender.NonResolving.Type("Class"));
ILineTree level3 = level2.Create(LineAppender.NonResolving.Key("Hello"));                
level3.AddValue("Hello World!");
LineWriterMap.Default.WriteLineTree(
    tree, 
    srcFilename: null, 
    dstFilename: "localization1.ini", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

IniLinesWriter writes tree as .ini file format, but flattens levels after second.

ILineTree tree = new LineTree();
ILineTree level1 = tree.Create(LineAppender.NonResolving.Culture("en"));
ILineTree level2 = level1.Create(LineAppender.NonResolving.Type("Class"));
ILineTree level3 = level2.Create(LineAppender.NonResolving.Key("Hello"));                
level3.AddValue("Hello World!");
LineWriterMap.Default.WriteLineTree(
    tree, 
    srcFilename: null, 
    dstFilename: "localization1.ini", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

JsonLinesWriter writes tree as .json file format.

LineWriterMap.Default.WriteLineTree(
    tree, 
    srcFilename: null, 
    dstFilename: "localization1.json", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

XmlLinesWriter writes tree as .xml file format.

LineWriterMap.Default.WriteLineTree(
    tree, 
    srcFilename: null, 
    dstFilename: "localization1.xml", 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

ResxLinesWriter writes tree as .resx file format. ILineFormat is required in order to formulate key into string.

LineWriterMap.Default.WriteLineTree(
    tree, 
    srcFilename: null, 
    dstFilename: "localization1.resx", 
    lineFormat: LineParameterPrinter.Default, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

ResourcesLinesWriter writes tree as .resources file format.

LineWriterMap.Default.WriteLineTree(
    tree, 
    srcFilename: null, 
    dstFilename: "localization1.resources", 
    lineFormat: LineParameterPrinter.Default, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

Writing to Stream

Lines can be written to Stream.

Stream stream = new MemoryStream();
IniLinesWriter.Default.WriteLines(
    lines, 
    srcStream: null, 
    dstStream: stream, 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

Writing to TextWriter

Lines can be written to TextWriter.

TextWriter textWriter = new StringWriter();
IniLinesWriter.Default.WriteLines(
    lines, 
    srcText: null, 
    dstText: textWriter, 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

Writing to String

Lines can be written to String.

string text = IniLinesWriter.Default.WriteLinesAsString(
    lines, 
    srcText: null, 
    lineFormat: null, 
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Overwrite);

Update File

Existing files can be updated. LineFileWriteFlags determines what kind of changes are allowed.

// Source
string text =
    @"; Comment\n" +
    @"[Type:MyController]\n" +
    @"Key:Hello = Hello World\n";
// Read lines
List<ILine> lines = IniLinesWriter.Default.ReadString(text).ToList();
// Add line
lines.Add(LineAppender.NonResolving.Culture("de").Type("Class").Key("Hello").Format("Hallo Welt"));
// Update
string newText = IniLinesWriter.Default.WriteLinesAsString(
    lines, 
    srcText: text, 
    lineFormat: null,
    flags: LineFileWriteFlags.Add | LineFileWriteFlags.Modify | 
           LineFileWriteFlags.Remove | LineFileWriteFlags.EffectiveKeyMatching);
LineFileWriteFlags Description
Add Permission to add new entries to the container.
Remove Permission to remove entires that no longer exist. Entry is removed recursively.
RemoveCautious Permission to remove entires that no longer exist, but be cautious. If entry contains unrecognized comments, elements, then entry is not removed recursively.
Modify Permission to modify values of existing entries.
Overwrite Overwrite contents of previous file. Add flag is required to be used with Overwrite.
EffectiveKeyMatching Matches when old and new files have different tree structure.

Implementing

ILineWriter is the root interface for localization writer classes. (Click here)


A class that implements ILineWriter must to implement one of its sub-interfaces. A one that best suits the underlying format.

class ExtFileFormatWriter : IUnformedLineTextWriter
{
    public string Extension => "ext";

    public void WriteUnformedLines(IEnumerable<KeyValuePair<string, IString>> lines, TextReader srcText, TextWriter dstText, ILineFormat lineFormat, LineFileWriteFlags flags)
    {
        foreach (var line in lines)
        {
            dstText.WriteLine($"{line.Key} = {line.Value.Text}");
        }
    }
}

Writer can be added to LineWriterMap

// Create writer
ILineWriter format = new ExtFileFormatWriter();

// Clone formats
LineFileFormatMap formats = LineWriterMap.Default.Clone();
// Add to clone
formats.Add(format);

// Or if in deploying application project, format can be added to the global singleton
(LineWriterMap.Default as IDictionary<string, ILineFileFormat>).Add(format);
Back to top Copyright © 2015-2020 Toni Kalajainen