Skip to content

Commit 0c8156a

Browse files
Alexejherojs6pak
andauthored
Add localization API (#64)
Co-authored-by: js6pak <kubastaron@hotmail.com>
1 parent f2da251 commit 0c8156a

14 files changed

+523
-86
lines changed

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
<ItemGroup>
3333
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
34-
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" />
34+
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" />
3535
</ItemGroup>
3636
<PropertyGroup>
3737
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)\stylecop.ruleset</CodeAnalysisRuleSet>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Reactor.Localization;
2+
3+
namespace Reactor.Example;
4+
5+
public class ExampleLocalizationProvider : LocalizationProvider
6+
{
7+
public override bool TryGetText(StringNames stringName, out string? result)
8+
{
9+
if (stringName == (StringNames) 1337)
10+
{
11+
switch (CurrentLanguage)
12+
{
13+
case SupportedLangs.English:
14+
result = "Cringe English";
15+
return true;
16+
17+
default:
18+
result = "Based " + CurrentLanguage;
19+
return true;
20+
}
21+
}
22+
23+
result = null;
24+
return false;
25+
}
26+
}

Reactor.Example/ExamplePlugin.cs

+20-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using BepInEx;
33
using BepInEx.Unity.IL2CPP;
44
using Il2CppInterop.Runtime.Attributes;
5+
using Reactor.Localization;
6+
using Reactor.Localization.Utilities;
57
using Reactor.Networking;
68
using Reactor.Networking.Attributes;
79
using Reactor.Networking.Rpc;
@@ -19,9 +21,14 @@ namespace Reactor.Example;
1921
[ReactorModFlags(ModFlags.RequireOnAllClients)]
2022
public partial class ExamplePlugin : BasePlugin
2123
{
24+
private static StringNames _helloStringName;
25+
2226
public override void Load()
2327
{
2428
this.AddComponent<ExampleComponent>();
29+
30+
_helloStringName = CustomStringName.CreateAndRegister("Hello!");
31+
LocalizationManager.Register(new ExampleLocalizationProvider());
2532
}
2633

2734
[RegisterInIl2Cpp]
@@ -34,19 +41,29 @@ public ExampleComponent(IntPtr ptr) : base(ptr)
3441
{
3542
TestWindow = new DragWindow(new Rect(60, 20, 0, 0), "Example", () =>
3643
{
44+
if (GUILayout.Button("Log CustomStringName"))
45+
{
46+
Logger<ExamplePlugin>.Info(TranslationController.Instance.GetString(_helloStringName));
47+
}
48+
49+
if (GUILayout.Button("Log localized string"))
50+
{
51+
Logger<ExamplePlugin>.Info(TranslationController.Instance.GetString((StringNames) 1337));
52+
}
53+
3754
if (AmongUsClient.Instance && PlayerControl.LocalPlayer)
3855
{
3956
if (GUILayout.Button("Send ExampleRpc"))
4057
{
41-
var name = PlayerControl.LocalPlayer.Data.PlayerName;
42-
Rpc<ExampleRpc>.Instance.Send(new ExampleRpc.Data($"Send: from {name}"), ackCallback: () =>
58+
var playerName = PlayerControl.LocalPlayer.Data.PlayerName;
59+
Rpc<ExampleRpc>.Instance.Send(new ExampleRpc.Data($"Send: from {playerName}"), ackCallback: () =>
4360
{
4461
Logger<ExamplePlugin>.Info("Got an acknowledgement for example rpc");
4562
});
4663

4764
if (!AmongUsClient.Instance.AmHost)
4865
{
49-
Rpc<ExampleRpc>.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {name} to host"));
66+
Rpc<ExampleRpc>.Instance.SendTo(AmongUsClient.Instance.HostId, new ExampleRpc.Data($"SendTo: from {playerName} to host"));
5067
}
5168
}
5269

Reactor.sln

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution
1212
AmongUs.props = AmongUs.props
1313
Directory.Build.props = Directory.Build.props
1414
nuget.config = nuget.config
15+
stylecop.json = stylecop.json
16+
stylecop.ruleset = stylecop.ruleset
1517
EndProjectSection
1618
EndProject
1719
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Networking.Shared", "Reactor.Networking.Shared\Reactor.Networking.Shared.csproj", "{1E68CA20-22EB-4E57-B525-81970BE6363D}"

Reactor/Localization/CustomStringName.cs

-82
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Globalization;
3+
4+
namespace Reactor.Localization.Extensions;
5+
6+
/// <summary>
7+
/// Provides extension methods for <see cref="SupportedLangs"/>.
8+
/// </summary>
9+
public static class SupportedLangsExtensions
10+
{
11+
/// <summary>
12+
/// Gets a <see cref="CultureInfo"/> from the specified <paramref name="language"/>.
13+
/// </summary>
14+
/// <param name="language">The <see cref="SupportedLangs"/>.</param>
15+
/// <returns>a <see cref="CultureInfo"/>.</returns>
16+
public static CultureInfo ToCultureInfo(this SupportedLangs language)
17+
{
18+
return language switch
19+
{
20+
SupportedLangs.English => CultureInfo.GetCultureInfo("en"),
21+
SupportedLangs.Latam => CultureInfo.GetCultureInfo("es"),
22+
SupportedLangs.Brazilian => CultureInfo.GetCultureInfo("pt-BR"),
23+
SupportedLangs.Portuguese => CultureInfo.GetCultureInfo("pt"),
24+
SupportedLangs.Korean => CultureInfo.GetCultureInfo("ko"),
25+
SupportedLangs.Russian => CultureInfo.GetCultureInfo("ru"),
26+
SupportedLangs.Dutch => CultureInfo.GetCultureInfo("nl"),
27+
SupportedLangs.Filipino => CultureInfo.GetCultureInfo("fil"),
28+
SupportedLangs.French => CultureInfo.GetCultureInfo("fr"),
29+
SupportedLangs.German => CultureInfo.GetCultureInfo("de"),
30+
SupportedLangs.Italian => CultureInfo.GetCultureInfo("it"),
31+
SupportedLangs.Japanese => CultureInfo.GetCultureInfo("ja"),
32+
SupportedLangs.Spanish => CultureInfo.GetCultureInfo("es"),
33+
SupportedLangs.SChinese => CultureInfo.GetCultureInfo("zh-Hans"),
34+
SupportedLangs.TChinese => CultureInfo.GetCultureInfo("zh-Hant"),
35+
SupportedLangs.Irish => CultureInfo.GetCultureInfo("ga"),
36+
_ => throw new ArgumentOutOfRangeException(nameof(language), language, null),
37+
};
38+
}
39+
}
+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using System.Collections.Generic;
2+
using Il2CppInterop.Runtime.InteropTypes.Arrays;
3+
4+
namespace Reactor.Localization;
5+
6+
/// <summary>
7+
/// Handles custom <see cref="StringNames"/> localization.
8+
/// </summary>
9+
public static class LocalizationManager
10+
{
11+
private static readonly List<LocalizationProvider> _providers = new();
12+
13+
/// <summary>
14+
/// Gets registered <see cref="LocalizationProvider"/>s.
15+
/// </summary>
16+
public static IReadOnlyList<LocalizationProvider> Providers { get; } = _providers.AsReadOnly();
17+
18+
/// <summary>
19+
/// Registers a new <see cref="LocalizationProvider"/> to be used for obtaining translations.
20+
/// </summary>
21+
/// <param name="provider">A <see cref="LocalizationProvider"/> instance.</param>
22+
public static void Register(LocalizationProvider provider)
23+
{
24+
if (!_providers.Contains(provider))
25+
{
26+
_providers.Add(provider);
27+
28+
if (TranslationController.InstanceExists)
29+
{
30+
provider.SetLanguage(TranslationController.Instance.currentLanguage.languageID);
31+
}
32+
33+
_providers.Sort((a, b) => b.Priority - a.Priority);
34+
}
35+
}
36+
37+
/// <summary>
38+
/// Unregisters a <see cref="LocalizationProvider"/>.
39+
/// </summary>
40+
/// <param name="provider">The <see cref="LocalizationProvider"/> to unregister.</param>
41+
public static void Unregister(LocalizationProvider provider)
42+
{
43+
_providers.Remove(provider);
44+
}
45+
46+
internal static bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray<Il2CppSystem.Object> parts, out string text)
47+
{
48+
foreach (var provider in _providers)
49+
{
50+
if (provider.TryGetTextFormatted(stringName, parts, out text!))
51+
{
52+
return true;
53+
}
54+
}
55+
56+
text = string.Empty;
57+
return false;
58+
}
59+
60+
internal static bool TryGetText(StringNames stringName, out string text)
61+
{
62+
foreach (var provider in _providers)
63+
{
64+
if (provider.TryGetText(stringName, out text!))
65+
{
66+
return true;
67+
}
68+
}
69+
70+
text = string.Empty;
71+
return false;
72+
}
73+
74+
internal static bool TryGetStringName(SystemTypes systemType, out StringNames stringName)
75+
{
76+
foreach (var provider in _providers)
77+
{
78+
if (provider.TryGetStringName(systemType, out var stringNameNullable))
79+
{
80+
stringName = stringNameNullable!.Value;
81+
return true;
82+
}
83+
}
84+
85+
stringName = default;
86+
return false;
87+
}
88+
89+
internal static bool TryGetStringName(TaskTypes taskTypes, out StringNames stringName)
90+
{
91+
foreach (var provider in _providers)
92+
{
93+
if (provider.TryGetStringName(taskTypes, out var stringNameNullable))
94+
{
95+
stringName = stringNameNullable!.Value;
96+
return true;
97+
}
98+
}
99+
100+
stringName = default;
101+
return false;
102+
}
103+
104+
internal static void OnLanguageChanged(SupportedLangs newLanguage)
105+
{
106+
foreach (var provider in _providers)
107+
{
108+
provider.SetLanguage(newLanguage);
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)