From c97f2adf7f00258968cfcd80d9fe258b33961baa Mon Sep 17 00:00:00 2001 From: Keith Pickford Date: Mon, 26 Feb 2024 09:56:25 +0000 Subject: [PATCH] Runtime translation decisions. Not final. --- .../FunctionZero.Maui.Controls.csproj | 2 +- .../Services/LanguageProvider.cs | 13 --- .../{ => Localisation}/BaseLanguageService.cs | 19 +++- .../Services/Localisation/ExpressionString.cs | 35 ++++++ .../LanguageChangedEventArgs.cs | 2 +- .../Services/Localisation/LanguageProvider.cs | 42 +++++++ SampleApp/MauiProgram.cs | 104 ++++++++++++++++-- .../Translations/TranslationHomePageVm.cs | 14 ++- SampleApp/Translations/LangService.cs | 2 +- SampleApp/Translations/LangStrings.cs | 3 +- 10 files changed, 202 insertions(+), 34 deletions(-) delete mode 100644 FunctionZero.Maui.Controls/Services/LanguageProvider.cs rename FunctionZero.Maui.Controls/Services/{ => Localisation}/BaseLanguageService.cs (80%) create mode 100644 FunctionZero.Maui.Controls/Services/Localisation/ExpressionString.cs rename FunctionZero.Maui.Controls/Services/{ => Localisation}/LanguageChangedEventArgs.cs (81%) create mode 100644 FunctionZero.Maui.Controls/Services/Localisation/LanguageProvider.cs diff --git a/FunctionZero.Maui.Controls/FunctionZero.Maui.Controls.csproj b/FunctionZero.Maui.Controls/FunctionZero.Maui.Controls.csproj index 62365a1..1aea57f 100644 --- a/FunctionZero.Maui.Controls/FunctionZero.Maui.Controls.csproj +++ b/FunctionZero.Maui.Controls/FunctionZero.Maui.Controls.csproj @@ -29,7 +29,7 @@ License.md True snupkg - 8.0.0.2-pre6 + 8.0.0.2-pre8 F0 gravatar.png diff --git a/FunctionZero.Maui.Controls/Services/LanguageProvider.cs b/FunctionZero.Maui.Controls/Services/LanguageProvider.cs deleted file mode 100644 index ec539d3..0000000 --- a/FunctionZero.Maui.Controls/Services/LanguageProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace FunctionZero.Maui.Services -{ - public class LanguageProvider - { - public LanguageProvider(Func getLookup, string languageName) - { - GetLookup = getLookup; - LanguageName = languageName; - } - public Func GetLookup { get; } - public string LanguageName { get; } - } -} diff --git a/FunctionZero.Maui.Controls/Services/BaseLanguageService.cs b/FunctionZero.Maui.Controls/Services/Localisation/BaseLanguageService.cs similarity index 80% rename from FunctionZero.Maui.Controls/Services/BaseLanguageService.cs rename to FunctionZero.Maui.Controls/Services/Localisation/BaseLanguageService.cs index 55006bd..ca43e96 100644 --- a/FunctionZero.Maui.Controls/Services/BaseLanguageService.cs +++ b/FunctionZero.Maui.Controls/Services/Localisation/BaseLanguageService.cs @@ -1,4 +1,5 @@ -using FunctionZero.Maui.MarkupExtensions; +using FunctionZero.ExpressionParserZero.BackingStore; +using FunctionZero.Maui.MarkupExtensions; using System; using System.Collections.Generic; using System.ComponentModel; @@ -7,7 +8,7 @@ using System.Text; using System.Threading.Tasks; -namespace FunctionZero.Maui.Services +namespace FunctionZero.Maui.Services.Localisation { /// /// Goal. To be decoupled enough to allow downloading and selection of new or updated language packs on the fly. @@ -68,10 +69,18 @@ public void SetLanguage(string id) public string[] CurrentLookup => _resourceHost[_resourceKey] as string[]; - public string GetText(TEnum textId) + public string GetText(TEnum textId, IBackingStore host) { - var retval = _languages[CurrentLanguageId].GetLookup()[(int)(object)textId]; - return retval; + var lookup = _languages[CurrentLanguageId].GetLookup()[(int)(object)textId]; + + foreach (var item in lookup) + { + var result = item.Item1.Evaluate(host).Pop(); + if (result.Type == ExpressionParserZero.Operands.OperandType.Bool) + if ((bool)result.GetValue() == true) + return item.Item2; + } + return $"textId {textId} not found."; } } } diff --git a/FunctionZero.Maui.Controls/Services/Localisation/ExpressionString.cs b/FunctionZero.Maui.Controls/Services/Localisation/ExpressionString.cs new file mode 100644 index 0000000..3bf443b --- /dev/null +++ b/FunctionZero.Maui.Controls/Services/Localisation/ExpressionString.cs @@ -0,0 +1,35 @@ +using FunctionZero.ExpressionParserZero.BackingStore; +using FunctionZero.ExpressionParserZero.Evaluator; + +namespace FunctionZero.Maui.Services.Localisation +{ + public class ExpressionString + { + private ExpressionTree _expression; + private readonly string _resultString; + + public ExpressionString(ExpressionTree expression, string resultString) + { + _expression = expression; + _resultString = resultString; + } + + public bool GetString(object backingStore, ref string result) + { + result = _resultString; + + try + { + if (backingStore is IBackingStore pocoBackingStore) + return (bool)_expression.Evaluate(pocoBackingStore).Pop().GetValue(); + else + return (bool)_expression.Evaluate(new PocoBackingStore(backingStore)).Pop().GetValue(); + } + catch(Exception ex) + { + result = ex.Message; + return false; + } + } + } +} \ No newline at end of file diff --git a/FunctionZero.Maui.Controls/Services/LanguageChangedEventArgs.cs b/FunctionZero.Maui.Controls/Services/Localisation/LanguageChangedEventArgs.cs similarity index 81% rename from FunctionZero.Maui.Controls/Services/LanguageChangedEventArgs.cs rename to FunctionZero.Maui.Controls/Services/Localisation/LanguageChangedEventArgs.cs index 2b5d315..596b84d 100644 --- a/FunctionZero.Maui.Controls/Services/LanguageChangedEventArgs.cs +++ b/FunctionZero.Maui.Controls/Services/Localisation/LanguageChangedEventArgs.cs @@ -1,4 +1,4 @@ -namespace FunctionZero.Maui.Services +namespace FunctionZero.Maui.Services.Localisation { public class LanguageChangedEventArgs : EventArgs { diff --git a/FunctionZero.Maui.Controls/Services/Localisation/LanguageProvider.cs b/FunctionZero.Maui.Controls/Services/Localisation/LanguageProvider.cs new file mode 100644 index 0000000..f6cb123 --- /dev/null +++ b/FunctionZero.Maui.Controls/Services/Localisation/LanguageProvider.cs @@ -0,0 +1,42 @@ +using FunctionZero.ExpressionParserZero.Binding; +using FunctionZero.ExpressionParserZero.Evaluator; + +namespace FunctionZero.Maui.Services.Localisation +{ + public class LanguageProvider + { + private readonly ExpressionTree _trueExpression; + + public LanguageProvider(Func>> getLookup, string languageName) + { + GetLookup = getLookup; + LanguageName = languageName; + } + //item.Add((parser.Parse("true"), "There are loads of bananas!")); + public LanguageProvider(Func> getLookup, string languageName) + { + var parser = ExpressionParserFactory.GetExpressionParser(); + _trueExpression = parser.Parse("true"); + + GetLookup = GetLookupFromStringList(getLookup); + LanguageName = languageName; + } + + private Func>> GetLookupFromStringList(Func> getLookup) + { + List> lookup = new List>(); + foreach (var theString in getLookup()) + { + var item = new List<(ExpressionTree, string)>(); + item.Add((_trueExpression, theString)); + lookup.Add(item); + } + return () => lookup; + } + + + //public Func GetLookup { get; } + public Func>> GetLookup { get; } + public string LanguageName { get; } + } +} diff --git a/SampleApp/MauiProgram.cs b/SampleApp/MauiProgram.cs index a4f1e90..b4538ab 100644 --- a/SampleApp/MauiProgram.cs +++ b/SampleApp/MauiProgram.cs @@ -1,9 +1,11 @@ using FunctionZero.ExpressionParserZero.Binding; using FunctionZero.ExpressionParserZero.Evaluator; +using FunctionZero.ExpressionParserZero.Operands; using FunctionZero.ExpressionParserZero.Parser; using FunctionZero.Maui.Controls; using FunctionZero.Maui.MvvmZero; using FunctionZero.Maui.Services; +using FunctionZero.Maui.Services.Localisation; using SampleApp.Mvvm.Pages; using SampleApp.Mvvm.Pages.Expander; using SampleApp.Mvvm.Pages.List; @@ -49,7 +51,7 @@ public static MauiApp CreateMauiApp() .MapVmToView() .MapVmToView() - + ; } ) @@ -121,21 +123,101 @@ private static LangService GetConfiguredLanguageService(IServiceProvider provide } // Example - private static string[] GetEnglish() => new string[] { "Hello", "World", "Welcome to the Moasure Playground!" }; - private static string[] GetGerman() => new string[] { "Hallo", "Welt", "Willkommen auf dem Moasure Spielplatz!" }; + //private static string[] GetEnglish() => new string[] { "Hello", "World", "Welcome to the Moasure Playground!" }; + private static string[] GetGerman() => new string[] { "Bananas", "Hallo", "Welt", "Willkommen auf dem Moasure Spielplatz!" }; - //private static List<(ExpressionTree, string)> GetEnglish2() - //{ - // var retval = new List<(ExpressionTree, string)>(); + private static List> GetEnglish() + { + var parser = ExpressionParserFactory.GetExpressionParser(); + var trueExpression = parser.Parse("true"); + + var retval = new List>(); + + { + var item = new List<(ExpressionTree, string)>(); + + item.Add((parser.Parse("NumBananas == 0"), "There are no bananas!")); + item.Add((parser.Parse("NumBananas == 1"), "There is one banana!")); + item.Add((parser.Parse("NumBananas == 2"), "There are two bananas!")); + item.Add((parser.Parse("NumBananas < 10"), "There are {NumBananas} bananas!")); // TODO: {NumBananas} + item.Add((parser.Parse("true"), "There are loads of bananas!")); + + //HashSet dependsOn = new HashSet(); + + //foreach(var tuple in item) + // foreach(var token in tuple.Item1.RpnTokens) + // if(token is Operand op) + // if(op.Type == OperandType.Variable) + // dependsOn.Add((string)op.GetValue()); + + retval.Add(item); + } + { + var item = new List<(ExpressionTree, string)>(); + + item.Add((trueExpression, "Hello!")); + + retval.Add(item); + } + { + var item = new List<(ExpressionTree, string)>(); + + item.Add((trueExpression, "World")); + + retval.Add(item); + } + { + var item = new List<(ExpressionTree, string)>(); + + item.Add((trueExpression, "This is a demonstration of FunctionZero Translation Service")); + retval.Add(item); + } + + + return retval; + } + + //private static List> GetGerman() + //{ // var parser = ExpressionParserFactory.GetExpressionParser(); + // var trueExpression = parser.Parse("true"); + + // var retval = new List>(); + + // { + // var item = new List<(ExpressionTree, string)>(); + + // item.Add((parser.Parse("NumBananas == 0"), "Es gibt keine Bananen!")); + // item.Add((parser.Parse("NumBananas == 1"), "Es gibt eine Banane!")); + // item.Add((parser.Parse("NumBananas == 2"), "Es gibt zwei Bananen!")); + // item.Add((parser.Parse("NumBananas < 10"), "Es gibt {NumBananas} Bananen!")); // TODO: {NumBananas} + // item.Add((parser.Parse("true"), "Es gibt jede Menge Bananen!")); + + // retval.Add(item); + // } + // { + // var item = new List<(ExpressionTree, string)>(); + + // item.Add((trueExpression, "Hallo!")); + + // retval.Add(item); + // } + // { + // var item = new List<(ExpressionTree, string)>(); + + // item.Add((trueExpression, "Welt")); + + // retval.Add(item); + // } + // { + // var item = new List<(ExpressionTree, string)>(); + + // item.Add((trueExpression, "Dies ist eine Demonstration des FunctionZero Translation Service")); - // retval.Add((parser.Parse("NumBananas == 0"), "There are no bananas!")); + // retval.Add(item); + // } - // retval.Add((parser.Parse("NumBananas == 1"), "There is one banana!")); - // retval.Add((parser.Parse("NumBananas == 2"), "There are two bananas!")); - // retval.Add((parser.Parse("NumBananas < 10"), "There are {NumBananas} bananas!")); // TODO: {NumBananas} - // retval.Add((parser.Parse("true"), "There are loads of bananas!")); // return retval; //} diff --git a/SampleApp/Mvvm/PageViewModels/Translations/TranslationHomePageVm.cs b/SampleApp/Mvvm/PageViewModels/Translations/TranslationHomePageVm.cs index 73c2e2c..e12a12b 100644 --- a/SampleApp/Mvvm/PageViewModels/Translations/TranslationHomePageVm.cs +++ b/SampleApp/Mvvm/PageViewModels/Translations/TranslationHomePageVm.cs @@ -1,4 +1,5 @@ using FunctionZero.CommandZero; +using FunctionZero.ExpressionParserZero.BackingStore; using FunctionZero.Maui.MvvmZero; using FunctionZero.Maui.Services; using SampleApp.Mvvm.ViewModels; @@ -23,6 +24,8 @@ public TranslationHomePageVm(LangService langService) { _langService = langService; + var thisAsPocoBackingStore = new PocoBackingStore(this); + SetLanguageCommand = new CommandBuilder() .AddGuard(this) .SetExecute(SetLanguageCommandExecute) @@ -31,9 +34,18 @@ public TranslationHomePageVm(LangService langService) DoTheThingCommand = new CommandBuilder() .AddGuard(this) .SetExecute(DoTheThingCommandExecute) - .SetName(() => langService.GetText(LangStrings.E_World)) + .SetName(() => langService.GetText(LangStrings.E_Bananas, thisAsPocoBackingStore)) .AddObservedProperty(langService, nameof(LangService.CurrentLanguageId)) .Build(); + + NumBananas = 1; + } + + private int _numBananas; + public int NumBananas + { + get => _numBananas; + set => SetProperty(ref _numBananas, value); } private void DoTheThingCommandExecute() diff --git a/SampleApp/Translations/LangService.cs b/SampleApp/Translations/LangService.cs index 23c2eba..8425888 100644 --- a/SampleApp/Translations/LangService.cs +++ b/SampleApp/Translations/LangService.cs @@ -1,5 +1,5 @@ using FunctionZero.Maui.MarkupExtensions; -using FunctionZero.Maui.Services; +using FunctionZero.Maui.Services.Localisation; using System; using System.Collections.Generic; using System.Linq; diff --git a/SampleApp/Translations/LangStrings.cs b/SampleApp/Translations/LangStrings.cs index efb6df0..06a627f 100644 --- a/SampleApp/Translations/LangStrings.cs +++ b/SampleApp/Translations/LangStrings.cs @@ -12,8 +12,9 @@ namespace SampleApp.Translations /// public enum LangStrings { + E_Bananas, E_Hello, E_World, - E_Welcome + E_Welcome, } }