ILocalizationFileFormat
ILocalizationFileFormat describes localization resource type, text or binary.
/// <summary>Localization file format</summary>
public interface ILocalizationFileFormat
{
/// <summary>Supported extensions, low case, with prefix dot. e.g. ".l.yaml", ".l.json", ".l.xml"</summary>
string[] Extensions { get; }
}
ILocalizationLineFileFormat describes localization text resource.
/// <summary>Localization line file format</summary>
public interface ILocalizationLineFileFormat : ILocalizationFileFormat
{
/// <summary>Read lines from <paramref name="stream"/>. Caller must close <paramref name="stream"/>.</summary>
/// <returns>Returns lines which must be read completely before call returns.</returns>
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> Read(Stream stream);
}
LocalizationFileFormat
There are three default line file formats.
ILocalizationFileFormat fileFormat1 = LocalizationFileFormatYaml.Instance;
ILocalizationFileFormat fileFormat2 = LocalizationFileFormatXml.Instance;
ILocalizationFileFormat fileFormat3 = LocalizationFileFormatJson.Instance;
localization.Files.FileFormats is list where supported localization file formats can be managed.
// Create localization
ILocalization localization = Localization.CreateDefault();
// Modify localization file formats
localization.Files.FileFormats.Remove(LocalizationFileFormatXml.Instance);
localization.Files.FileFormats.Remove(LocalizationFileFormatJson.Instance);
File Format
Localization file has tree structure that describes lines as key-value properties (See line). There are three file formats.
# Configuration
TemplateFormat: BraceNumeric
PluralRules: Unicode.CLDR41
English:
- Culture: en
Items:
- Key: Namespace.Apples
Text: "You've got {0} apple(s)."
- Key: Namespace.ExitRoundabout
Text: "Take exit number {0}."
Finnish:
- Culture: fi
Items:
- Key: Namespace.Apples
Text: "Sinulla on {0} omena(a)."
- Key: Namespace.ExitRoundabout
Text: "Poistu {0}. erkanemiskaistalta."
When pluralization is used, a Text for each required case must be supplied. Cases and requirements are language specific, see CLDR42.
TemplateFormat: BraceNumeric
PluralRules: Unicode.CLDR41
English:
- Culture: en
Items:
- Key: Namespace.Apples
Cases:
- Text: "You've got an apple."
Plurals: "0:cardinal:one"
- Text: "You've got {0} apples."
Plurals: "0:cardinal:other"
Finnish:
- Culture: fi
Items:
- Key: Namespace.Apples
Cases:
- Text: "Sinulla on yksi omena."
Plurals: "0:cardinal:one"
- Text: "Sinulla on {0} omenaa."
Plurals: "0:cardinal:other"
Some cases are not required (see), such as zero case for english language. The "You've got no apples." can be optionally supplied, but if not, the "You've got 0 apples" works with same template as "You've got 2 apples.".
# Configuration
TemplateFormat: BraceNumeric
PluralRules: Unicode.CLDR41
English:
- Culture: en
Items:
- Key: Namespace.Apples
Cases:
- Text: "You've got no apples."
Plurals: "0:cardinal:zero"
- Text: "You've got an apple."
Plurals: "0:cardinal:one"
- Text: "You've got {0} apples."
Plurals: "0:cardinal:other"
Finnish:
- Culture: fi
Items:
- Key: Namespace.Apples
Cases:
- Text: "Sinulla ei ole omenoita."
Plurals: "0:cardinal:zero"
- Text: "Sinulla on yksi omena."
Plurals: "0:cardinal:one"
- Text: "Sinulla on {0} omenaa."
Plurals: "0:cardinal:other"
Lines with order numbers are supplied using ordinal category. [Demo]
# Configuration
TemplateFormat: BraceNumeric
PluralRules: Unicode.CLDR41
English:
- Culture: en
Items:
- Key: Namespace.ExitRoundabout
Cases:
- Text: "Take first exit."
Plurals: "0:ordinal:one"
- Text: "Take second exit."
Plurals: "0:ordinal:two"
- Text: "Take third exit."
Plurals: "0:ordinal:few"
- Text: "Take {0}th exit."
Plurals: "0:ordinal:other"
Finnish:
- Culture: fi
Items:
- Key: Namespace.ExitRoundabout
Text: "Poistu {0}. erkanemiskaistalta."
Plurals: "0:ordinal:other"
Reader
LocalizationReaderYaml.File(filename) reads .l.yml files.
// Filename
string filename = "localizationfileformat/localization1.l.yaml";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderYaml.File(filename);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
Reader flattens a structural localization file into the intermediate format IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>>.
TemplateFormat=BraceNumeric, PluralRules=Unicode.CLDR40, Culture=en, Key=Namespace.Apples, Text=You've got {0} apple(s)., Plurals=0:cardinal:other TemplateFormat=BraceNumeric, PluralRules=Unicode.CLDR40, Culture=en, Key=Namespace.ExitRoundabout, Text=Take exit number {0}., Plurals=0.ordinal:other TemplateFormat=BraceNumeric, PluralRules=Unicode.CLDR40, Culture=fi, Key=Namespace.Apples, Text=Sinulla on {0} omena(a)., Plurals=0:cardinal:other TemplateFormat=BraceNumeric, PluralRules=Unicode.CLDR40, Culture=fi, Key=Namespace.ExitRoundabout, Text=Poistu {0}. erkanemiskaistalta., Plurals=0:ordinal:other
.ToArray() activates the reader to read the file into an array.
IEnumerable<KeyValuePair<string, MarkedText>>[] lines = new LocalizationReaderYaml.File("localizationfileformat/localization1.l.yaml").ToArray();
.AnnotateFilename(filename) decorates reader to override the filename used in error diagnostics.
var reader = new LocalizationReaderYaml.File("localizationfileformat/localization1.l.yaml").AnnotateFilename("localization.l.yml");
LocalizationReaderYaml.Text(text) reads localization from yml string.
string text = @"TemplateFormat: BraceNumeric
PluralRules: Unicode.CLDR41
English:
- Culture: en
Items:
- Key: Namespace.Apples
Text: ""You've got {0} apple(s).""";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderYaml.Text(text);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
Full Example
Full example
using Avalanche.Localization;
using Avalanche.Utilities;
using static System.Console;
class localizationfileformat
{
public static void Run()
{
{
// <01>
ILocalizationFileFormat fileFormat1 = LocalizationFileFormatYaml.Instance;
ILocalizationFileFormat fileFormat2 = LocalizationFileFormatXml.Instance;
ILocalizationFileFormat fileFormat3 = LocalizationFileFormatJson.Instance;
// </01>
}
{
// <02>
// Create localization
ILocalization localization = Localization.CreateDefault();
// Modify localization file formats
localization.Files.FileFormats.Remove(LocalizationFileFormatXml.Instance);
localization.Files.FileFormats.Remove(LocalizationFileFormatJson.Instance);
// </02>
}
{
// <11>
// Create xml file reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> localizationLines = new LocalizationReaderXml.File(@"localizationfileformat\localization1.l.xml");
// Read and print lines
foreach (var line in localizationLines) WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </11>
}
{
// <12>
// Create intermediate format of localization lines
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> localizationLines =
new Dictionary<string, MarkedText>[]
{
new Dictionary<string, MarkedText>{ { "TemplateFormat", "BraceNumeric" }, { "Culture", "en" }, { "Key", "Namespace.Apples" }, { "Text", "You've got {0} apple(s)." } },
new Dictionary<string, MarkedText>{ { "TemplateFormat", "BraceNumeric" }, { "Culture", "en" }, { "Key", "Namespace.ExitRoundabout" }, { "Text", "Take exit number {0}." } },
};
// Print lines
foreach (var line in localizationLines) WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </12>
}
}
}
using System.Globalization;
using Avalanche.Localization;
using Avalanche.Utilities;
using Microsoft.Extensions.FileProviders;
using YamlDotNet.RepresentationModel;
using static System.Console;
class yaml
{
public static void Run()
{
{
// <01>
// Filename
string filename = "localizationfileformat/localization1.l.yaml";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderYaml.File(filename);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </01>
}
{
// <01a>
IEnumerable<KeyValuePair<string, MarkedText>>[] lines = new LocalizationReaderYaml.File("localizationfileformat/localization1.l.yaml").ToArray();
// </01a>
}
{
// <01b>
var reader = new LocalizationReaderYaml.File("localizationfileformat/localization1.l.yaml").AnnotateFilename("localization.l.yml");
// </01b>
}
{
// <02>
string text = @"TemplateFormat: BraceNumeric
PluralRules: Unicode.CLDR41
English:
- Culture: en
Items:
- Key: Namespace.Apples
Text: ""You've got {0} apple(s).""";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderYaml.Text(text);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </02>
}
{
// <03>
// Create document
YamlDocument document = new YamlDocument("");
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderYaml.Document(document);
// </03>
}
{
// <05>
IFileProvider fileProvider = new PhysicalFileProvider(Path.GetFullPath("localizationfileformat"));
var reader = new LocalizationReaderYamlFromFileProvider(fileProvider, "localization1.l.yaml");
var lines = reader.ToArray();
// </05>
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
}
}
}
using System.Globalization;
using System.Xml.Linq;
using Avalanche.Localization;
using Avalanche.Utilities;
using Microsoft.Extensions.FileProviders;
using YamlDotNet.RepresentationModel;
using static System.Console;
class xml
{
public static void Run()
{
{
// <01>
// Filename
string filename = "localizationfileformat/localization1.l.xml";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderXml.File(filename);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </01>
}
{
// <01a>
IEnumerable<KeyValuePair<string, MarkedText>>[] lines = new LocalizationReaderXml.File("localizationfileformat/localization1.l.xml").ToArray();
// </01a>
}
{
// <01b>
var reader = new LocalizationReaderXml.File("localizationfileformat/localization1.l.xml").AnnotateFilename("localization.l.xml");
// </01b>
}
{
// <01c>
// Filename
string filename = "localizationfileformat/localization1c.l.xml";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderXml.File(filename);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </01c>
}
{
// <02>
string text = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Localization TemplateFormat=""BraceNumeric"" PluralRules=""Unicode.CLDR40"">
<N Culture=""en"">
<N Key=""Namespace.Apples"">
<Text Plurals=""0:cardinal:one"">You've got an apple.</Text>
<Text Plurals=""0:cardinal:other"">You've got {0} apples.</Text>
</N>
<N Key=""Namespace.ExitRoundabout"">
<Text Plurals=""0:ordinal:one"">Take first exit.</Text>
<Text Plurals=""0:ordinal:two"">Take second exit.</Text>
<Text Plurals=""0:ordinal:few"">Take third exit.</Text>
<Text Plurals=""0:ordinal:other"">Take {0}th exit.</Text>
</N>
</N>
</Localization>
";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderXml.Text(text);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </02>
}
{
// <03>
// Create document
XDocument document = new XDocument();
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderXml.Document(document);
// </03>
}
{
// <05>
IFileProvider fileProvider = new PhysicalFileProvider(Path.GetFullPath("localizationfileformat"));
var reader = new LocalizationReaderXmlFromFileProvider(fileProvider, "localization1.l.xml");
var lines = reader.ToArray();
// </05>
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
}
}
}
using System.Text.Json.Nodes;
using Avalanche.Localization;
using Avalanche.Utilities;
using Microsoft.Extensions.FileProviders;
using static System.Console;
class json
{
public static void Run()
{
{
// <01>
// Filename
string filename = "localizationfileformat/localization1.l.json";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderJson.File(filename);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </01>
}
{
// <01a>
IEnumerable<KeyValuePair<string, MarkedText>>[] lines = new LocalizationReaderJson.File("localizationfileformat/localization1.l.json").ToArray();
// </01a>
}
{
// <01b>
var reader = new LocalizationReaderJson.File("localizationfileformat/localization1.l.json").AnnotateFilename("localization.l.json");
// </01b>
}
{
// <02>
string text = @"
{
""TemplateFormat"": ""BraceNumeric"",
""PluralRules"": ""Unicode.CLDR40"",
""English"": {
""Culture"": ""en"",
""Items"": [
{
""Key"": ""Namespace.Apples"",
""Items"": [
{
""Text"": ""You've got no apples."",
""Plurals"": ""0:cardinal:zero""
},
{
""Text"": ""You've got an apple."",
""Plurals"": ""0:cardinal:one""
},
{
""Text"": ""You've got {0} apples."",
""Plurals"": ""0:cardinal:other""
}
]
},
{
""Key"": ""Namespace.ExitRoundabout"",
""Items"": [
{
""Text"": ""Take first exit."",
""Plurals"": ""0:ordinal:one""
},
{
""Text"": ""Take second exit."",
""Plurals"": ""0:ordinal:two""
},
{
""Text"": ""Take third exit."",
""Plurals"": ""0:ordinal:few""
},
{
""Text"": ""Take {0}th exit."",
""Plurals"": ""0:ordinal:other""
}
]
}
]
}
}
";
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderJson.Text(text);
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
// </02>
}
{
// <03>
// Create document
JsonNode document = JsonNode.Parse("{}")!;
// Create reader
IEnumerable<IEnumerable<KeyValuePair<string, MarkedText>>> reader = new LocalizationReaderJson.Node(document);
// </03>
}
{
// <05>
IFileProvider fileProvider = new PhysicalFileProvider(Path.GetFullPath("localizationfileformat"));
var reader = new LocalizationFileReaderJsonFromFileProvider(fileProvider, "localization1.l.json");
var lines = reader.ToArray();
// </05>
// Read and print lines
foreach (var line in reader)
WriteLine(string.Join(", ", line.Select(a => $"{a.Key}={a.Value.AsString}")));
}
}
}