Add core classes.

This commit is contained in:
2019-05-23 22:15:57 +01:00
parent abf6e04a3f
commit 29e34556fb
10 changed files with 650 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,32 @@
namespace Claunia.Localization.Core
{
/// <summary>Enumerates programming languages for parameters</summary>
public enum Language
{
C,
ObjectiveC,
CSharp,
Shell,
Python,
Lisp,
EmacsLisp,
PythonBraced,
Librep,
Scheme,
Smalltalk,
Java,
Awk,
ObjectPascal,
Ycp,
Tcl,
Perl,
Php,
GccInternal,
GfcInternal,
Qt,
QtPlural,
Kde,
Boost,
JavaScript
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace Claunia.Localization.Core
{
/// <summary>
/// Represents the localization
/// </summary>
public class Localization
{
readonly ObservableCollection<Message> messages;
readonly ObservableCollection<Translator> translators;
public Localization()
{
Creation = DateTime.UtcNow;
LastWritten = DateTime.UtcNow;
Project = new Project();
Project.ProjectModified += OnModified;
translators = new ObservableCollection<Translator>();
Translators = new ReadOnlyObservableCollection<Translator>(translators);
translators.CollectionChanged += OnModified;
messages = new ObservableCollection<Message>();
Messages = new ReadOnlyObservableCollection<Message>(messages);
messages.CollectionChanged += OnModified;
}
/// <summary>Date this localization has been created</summary>
public DateTime Creation { get; }
/// <summary>Date this localization has been modified</summary>
public DateTime LastWritten { get; private set; }
/// <summary>Project this localization belongs to</summary>
public Project Project { get; }
/// <summary>List of translators that have worked in this localization</summary>
public ReadOnlyObservableCollection<Translator> Translators { get; }
/// <summary>
/// List of messages present in this localization
/// </summary>
public ReadOnlyObservableCollection<Message> Messages { get; }
void OnModified(object sender, EventArgs args)
{
LastWritten = DateTime.UtcNow;
}
/// <summary>
/// Adds a new translator to the localization
/// </summary>
/// <param name="name">Translator full name, english-form, in ASCII</param>
/// <param name="email">Translator e-mail</param>
/// <param name="nativeName">Translator full name, in native form</param>
/// <returns>The new translator</returns>
public Translator NewTranslator(string name, string email, string nativeName = null)
{
int id = translators.Max(t => t.Id) + 1;
Translator translator = new Translator(id) {Name = name, Email = email};
translator.Modified += OnModified;
translators.Add(translator);
return translator;
}
/// <summary>
/// Removes a translator from the localization
/// </summary>
/// <param name="translator">Translator to remove</param>
/// <returns><c>true</c> if the translator has been removed successfully, <c>false</c> otherwise</returns>
public bool RemoveTranslator(Translator translator) => !(translator is null) && translators.Remove(translator);
/// <summary>
/// Removes a translator from the localization
/// </summary>
/// <param name="id">ID of the translator to remove</param>
/// <returns><c>true</c> if the translator has been removed successfully, <c>false</c> otherwise</returns>
public bool RemoveTranslator(int id)
{
Translator translator = translators.FirstOrDefault(t => t.Id == id);
return !(translator is null) && translators.Remove(translator);
}
public Message NewMessage()
{
Message message = new Message();
message.Modified += OnModified;
messages.Add(message);
return message;
}
public bool RemoveMessage(Message message) => !(message is null) && messages.Remove(message);
public bool RemoveMessage(string id)
{
Message message = messages.FirstOrDefault(t => t.Id == id);
return !(message is null) && messages.Remove(message);
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.ObjectModel;
namespace Claunia.Localization.Core
{
/// <summary>
/// Represent a localized string
/// </summary>
public sealed class LocalizedString
{
readonly ObservableCollection<Plural> plurals;
string comments;
string locale;
internal EventHandler Modified;
string singular;
int? translator;
internal LocalizedString()
{
plurals = new ObservableCollection<Plural>();
plurals.CollectionChanged += (sender, args) => Modified?.Invoke(this, EventArgs.Empty);
Plurals = new ReadOnlyObservableCollection<Plural>(plurals);
}
/// <summary>
/// Contains the singular, or only, text for this string
/// </summary>
public string Singular
{
get => singular;
set
{
singular = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Which locale this string is in. Format is ll_CC with ll as ISO 639-2 language code and CC as ISO 3166 two letter
/// uppercase country code. _CC can be omitted.
/// </summary>
public string Locale
{
get => locale;
set
{
locale = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// ID of the translator, in this localization, that wrote this string
/// </summary>
public int? Translator
{
get => translator;
set
{
translator = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Translator comments
/// </summary>
public string Comments
{
get => comments;
set
{
comments = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Plural forms for this string
/// </summary>
public ReadOnlyObservableCollection<Plural> Plurals { get; }
/// <summary>
/// Initializes a new plural in this message
/// </summary>
/// <returns>The newly initialized plural</returns>
public Plural NewPlural()
{
Plural parameter = new Plural();
parameter.Modified += Modified;
plurals.Add(parameter);
return parameter;
}
/// <summary>
/// Removes a plural
/// </summary>
/// <param name="parameter">The plural to remove</param>
/// <returns><c>true</c> if the plural string has been removed successfully, <c>false</c> otherwise</returns>
public bool RemovePlural(Plural parameter) => plurals.Remove(parameter);
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.Collections.ObjectModel;
namespace Claunia.Localization.Core
{
/// <summary>
/// Represent a message and its translations
/// </summary>
public sealed class Message
{
readonly ObservableCollection<Parameter> parameters;
readonly ObservableCollection<LocalizedString> translations;
string comments;
string context;
string id;
internal EventHandler Modified;
string previousContext;
string reference;
internal Message()
{
Source = new LocalizedString();
Source.Modified += Modified;
translations = new ObservableCollection<LocalizedString>();
translations.CollectionChanged += (sender, args) => Modified?.Invoke(this, EventArgs.Empty);
parameters = new ObservableCollection<Parameter>();
parameters.CollectionChanged += (sender, args) => Modified?.Invoke(this, EventArgs.Empty);
Translations = new ReadOnlyObservableCollection<LocalizedString>(translations);
Parameters = new ReadOnlyObservableCollection<Parameter>(parameters);
}
/// <summary>
/// Describes the context where this message occurs
/// </summary>
public string Context
{
get => context;
set
{
context = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Describes the context where the previous version of this message occurred
/// </summary>
public string PreviousContext
{
get => previousContext;
set
{
previousContext = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Comments added by the original writer of the message
/// </summary>
public string Comments
{
get => comments;
set
{
comments = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Source code line reference or equivalent
/// </summary>
public string Reference
{
get => reference;
set
{
reference = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Unique identifier of this message
/// </summary>
public string Id
{
get => id;
set
{
id = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Original locale of this message
/// </summary>
public LocalizedString Source { get; }
/// <summary>
/// List of translations
/// </summary>
public ReadOnlyObservableCollection<LocalizedString> Translations { get; }
/// <summary>
/// List of parameters
/// </summary>
public ReadOnlyObservableCollection<Parameter> Parameters { get; }
/// <summary>
/// Initializes a new localized string in this message
/// </summary>
/// <returns>The newly initialized localized string</returns>
public LocalizedString NewLocalizedString()
{
LocalizedString localizedString = new LocalizedString();
localizedString.Modified += Modified;
translations.Add(localizedString);
return localizedString;
}
/// <summary>
/// Removes a localized string
/// </summary>
/// <param name="localizedString">The localized string to remove</param>
/// <returns><c>true</c> if the localized string has been removed successfully, <c>false</c> otherwise</returns>
public bool RemoveLocalizedString(LocalizedString localizedString) => translations.Remove(localizedString);
/// <summary>
/// Initializes a new parameter in this message
/// </summary>
/// <returns>The newly initialized parameter</returns>
public Parameter NewParameter()
{
Parameter parameter = new Parameter();
parameter.Modified += Modified;
parameters.Add(parameter);
return parameter;
}
/// <summary>
/// Removes a parameter
/// </summary>
/// <param name="parameter">The parameter to remove</param>
/// <returns><c>true</c> if the parameter string has been removed successfully, <c>false</c> otherwise</returns>
public bool RemoveParameter(Parameter parameter) => parameters.Remove(parameter);
}
}

View File

@@ -0,0 +1,97 @@
using System;
namespace Claunia.Localization.Core
{
/// <summary>
/// Explanation of a parameter in a software string to help the translator understand the context and for translation
/// helping software to be able to provide appropriate examples
/// </summary>
public class Parameter
{
string description;
int index;
Language language;
long? maximum;
long? minimum;
internal EventHandler Modified;
string type;
/// <summary>
/// Index of parameter in source message
/// </summary>
public int Index
{
get => index;
set
{
index = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Programming language for interpretation of messages
/// </summary>
public Language Language
{
get => language;
set
{
language = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Simple (single-word) description of parameter type
/// </summary>
public string Type
{
get => type;
set
{
type = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Minimum value the parameter can get
/// </summary>
public long? Minimum
{
get => minimum;
set
{
minimum = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Maximum value the parameter can get
/// </summary>
public long? Maximum
{
get => maximum;
set
{
maximum = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Description of the parameter
/// </summary>
public string Description
{
get => description;
set
{
description = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Claunia.Localization.Core
{
/// <summary>
/// Contains the plural forms of a string
/// </summary>
public class Plural
{
int items;
internal EventHandler Modified;
string text;
/// <summary>
/// Minimum number (inclusive) of items named to use this plural form
/// </summary>
public int Items
{
get => items;
set
{
items = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Plural form of the string
/// </summary>
public string Text
{
get => text;
set
{
text = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
namespace Claunia.Localization.Core
{
public class Project
{
string name;
internal EventHandler ProjectModified;
string url;
string version;
/// <summary>
/// Project name
/// </summary>
public string Name
{
get => name;
set
{
name = value;
ProjectModified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Project version
/// </summary>
public string Version
{
get => version;
set
{
version = value;
ProjectModified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Project URL
/// </summary>
public string Url
{
get => url;
set
{
url = value;
ProjectModified?.Invoke(this, EventArgs.Empty);
}
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
namespace Claunia.Localization.Core
{
public class Translator
{
string email;
internal EventHandler Modified;
string name;
string nativeName;
internal Translator(int id)
{
Id = id;
}
/// <summary>
/// Translator ID, unique in the corresponding localization, and sequential
/// </summary>
public int Id { get; }
/// <summary>
/// Translator e-mail
/// </summary>
public string Email
{
get => email;
set
{
email = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Translator name, in ASCII, english form
/// </summary>
public string Name
{
get => name;
set
{
name = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Translator full name in native form
/// </summary>
public string NativeName
{
get => nativeName ?? Name;
set
{
if(value == name) return;
nativeName = value;
Modified?.Invoke(this, EventArgs.Empty);
}
}
}
}

View File

@@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Claunia.Localization", "Cla
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Claunia.Localization.Desktop", "Claunia.Localization\Claunia.Localization.Desktop\Claunia.Localization.Desktop.csproj", "{258FEA96-4E93-4C8F-94EF-1319F93B350D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Claunia.Localization.Core", "Claunia.Localization.Core\Claunia.Localization.Core.csproj", "{CFDFDFC7-9662-4C50-B86A-9E579ACD3DF9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -20,5 +22,9 @@ Global
{258FEA96-4E93-4C8F-94EF-1319F93B350D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{258FEA96-4E93-4C8F-94EF-1319F93B350D}.Release|Any CPU.Build.0 = Release|Any CPU
{258FEA96-4E93-4C8F-94EF-1319F93B350D}.Release|Any CPU.Deploy.0 = Release|Any CPU
{CFDFDFC7-9662-4C50-B86A-9E579ACD3DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CFDFDFC7-9662-4C50-B86A-9E579ACD3DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CFDFDFC7-9662-4C50-B86A-9E579ACD3DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CFDFDFC7-9662-4C50-B86A-9E579ACD3DF9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal