Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions MN.L10n.Benchmark/MN.L10n.Benchmark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,25 @@
<ProjectReference Include="..\MN.L10n\MN.L10n.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="language-1.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="language-2.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="language-3.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="language-4.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="languages.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="phrases.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
21 changes: 14 additions & 7 deletions MN.L10n.Benchmark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using MN.L10n;
using MN.L10n.FileProviders;
using System.Collections.Concurrent;
using System.Reflection;
using System.Text;
Expand All @@ -10,7 +11,7 @@



BenchmarkRunner.Run<SpanTest>();
BenchmarkRunner.Run<Benchmarks>();



Expand All @@ -19,7 +20,7 @@ public class BenchmarkL10nLanguageProvider : IL10nLanguageProvider
{
public string GetLanguage()
{
return "0";
return "1";
}
}

Expand Down Expand Up @@ -55,10 +56,10 @@ public class Foo
}

[MemoryDiagnoser(true)]
[InvocationCount(1_000_000)]
public class SpanTest
[InvocationCount(100_000)]
public class Benchmarks
{
[Params("$data$", "Hej $data$ $count$ $many$", "$den här texten inleds med $data$$data2$")]
[Params("$data$", "Hej $data$ $count$ $many$", "$den här texten inleds med $data$$data2$", "Här har vi en längre förklarande text utan dollartecken. Den här skulle t.ex. kunna finnas i ")]
public string formatString { get; set; } = "";
public static Foo args = new Foo { data = "Anders" };

Expand All @@ -68,9 +69,9 @@ public void GlobalSetup()
var dataProvider = new BenchmarkL10nDataProvider();

var stack = new Stack<string>();
stack.Push("0");
stack.Push("1");
var items = new Dictionary<object, object>() { { "___l10nlang", stack } };
var l10n = L10n.CreateInstance(new BenchmarkL10nLanguageProvider(), dataProvider, () => items);
var l10n = L10n.CreateInstance(new BenchmarkL10nLanguageProvider(), new FileDataProvider(AppDomain.CurrentDomain.BaseDirectory), () => items);
dataProvider.SaveL10n(l10n);
}

Expand All @@ -80,6 +81,12 @@ public void GetPhase()
L10n._s(formatString, args);
}

[Benchmark]
public void GetPhaseWithoutArgs()
{
L10n._s(formatString);
}

[Benchmark]
public void FormatNamed()
{
Expand Down
43 changes: 24 additions & 19 deletions MN.L10n/L10n.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
using System.Threading;
using System.Threading.Tasks;
using MN.L10n.PhraseMetadata;
using System.Reflection;
using System.Text;
using System.Xml;

namespace MN.L10n
{
Expand Down Expand Up @@ -140,19 +143,21 @@ internal L10nTranslatedString __getPhrase(string phrase, object args = null)
{
if (lang.Phrases.TryGetValue(cleanedPhrase, out var phr))
{
if (phr.r.ContainsKey("0"))
string getVal;

if (phr.r.TryGetValue("0", out getVal))
{
cleanedPhrase = phr.r["0"];
cleanedPhrase = getVal;
}

if (isPluralized && lang.AstPluralRule != null)
{
// Here there be dragons
// Dynamic evaluation to get the phrase to use, based on the pluralization rule specified
var phraseIndex = lang.AstPluralRule.Evaluate(GetCount(args)).ToString();
if (phr.r.ContainsKey(phraseIndex))
if (phr.r.TryGetValue(phraseIndex, out getVal))
{
cleanedPhrase = phr.r[phraseIndex];
cleanedPhrase = getVal;
}
}
}
Expand Down Expand Up @@ -182,41 +187,41 @@ internal L10nTranslatedString __getPhrase(string phrase, object args = null)
return FormatNamed(withoutMetadata, args);
}

private static ConcurrentDictionary<Type, PropertyInfo> IsPluralizedCache = new ConcurrentDictionary<Type, PropertyInfo>();

public static bool IsPluralized(object args = null)
{
if (args == null) return false;
var t = args.GetType();
foreach (var p in t.GetProperties())
{
if (p.Name == "__count") return true;
}

return false;
var t = args.GetType();
return IsPluralizedCache.GetOrAdd(t, t.GetProperty("__count")) is not null;
}

public static long GetCount(object args = null)
{
if (args == null) return 0;
var t = args.GetType();
foreach (var p in t.GetProperties())
IsPluralizedCache.TryGetValue(args.GetType(), out var p);

if(p is not null)
{
if (p.Name == "__count")
{
long.TryParse(p.GetValue(args).ToString(), out long __count);
return __count;
}
return Convert.ToInt64(p.GetValue(args));

}

return 0;
}

private static ConcurrentDictionary<Type, PropertyInfo[]> propCache = new ConcurrentDictionary<Type, PropertyInfo[]>();

public static L10nTranslatedString FormatNamed(string formatString, object args = null)
{
if (args == null) return new L10nTranslatedString(formatString);

var t = args.GetType();
var tmpVal = formatString;
foreach (var p in t.GetProperties())

var props = propCache.GetOrAdd(t, tp => tp.GetProperties());

foreach (var p in props)
{
tmpVal = tmpVal.Replace("$" + p.Name + "$", p.GetValue(args)?.ToString());
}
Expand Down
4 changes: 2 additions & 2 deletions MN.L10n/MN.L10n.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net48;netstandard2.0;net8.0;net9.0</TargetFrameworks>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Company>MultiNet Interactive AB</Company>
<Authors>Chris Gårdenberg</Authors>
Expand Down Expand Up @@ -29,7 +29,7 @@ Translation package</Description>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
Expand Down
Loading