Add TranslationProvider

This commit is contained in:
Matthias Mailänder
2023-04-13 17:14:01 +03:00
committed by Matthias Mailänder
parent a065e6a47c
commit 68eec52cef
66 changed files with 384 additions and 333 deletions

View File

@@ -581,7 +581,7 @@ namespace OpenRA
Log.Write("debug", "Taking screenshot " + path);
Renderer.SaveScreenshot(path);
TextNotificationsManager.Debug(ModData.Translation.GetString(SavedScreenshot, Translation.Arguments("filename", filename)));
TextNotificationsManager.Debug(TranslationProvider.GetString(SavedScreenshot, Translation.Arguments("filename", filename)));
}
}

View File

@@ -256,8 +256,6 @@ namespace OpenRA
CellLayer<byte> projectedHeight;
Rectangle projectionSafeBounds;
internal Translation Translation;
public static string ComputeUID(IReadOnlyPackage package)
{
return ComputeUID(package, GetMapFormat(package));
@@ -450,8 +448,6 @@ namespace OpenRA
}
Sequences = new SequenceSet(this, modData, Tileset, SequenceDefinitions);
Translation = TranslationDefinitions == null ? null
: new Translation(Game.Settings.Player.Language, FieldLoader.GetValue<string[]>("value", TranslationDefinitions.Value), this);
var tl = new MPos(0, 0).ToCPos(this);
var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
@@ -1411,14 +1407,6 @@ namespace OpenRA
return false;
}
public string Translate(string key, IDictionary<string, object> args = null)
{
if (Translation != null && Translation.TryGetString(key, out var message, args))
return message;
return modData.Translation.GetString(key, args);
}
public void Dispose()
{
Sequences.Dispose();

View File

@@ -199,10 +199,14 @@ namespace OpenRA
public long DownloadBytes { get; private set; }
public int DownloadPercentage { get; private set; }
/// <summary>
/// Functionality mirrors <see cref="TranslationProvider.GetString"/>, except instead of using
/// loaded <see cref="Map"/>'s translations as backup, we use this <see cref="MapPreview"/>'s.
/// </summary>
public string GetLocalisedString(string key, IDictionary<string, object> args = null)
{
// PERF: instead of loading mod level Translation for each MapPreview, reuse the already loaded one in modData.
if (modData.Translation.TryGetString(key, out var message, args))
// PERF: instead of loading mod level Translation per each MapPreview, reuse the already loaded one in TranslationProvider.
if (TranslationProvider.TryGetModString(key, out var message, args))
return message;
return innerData.Translation?.GetString(key, args) ?? key;

View File

@@ -36,7 +36,6 @@ namespace OpenRA
public readonly IModelSequenceLoader ModelSequenceLoader;
public readonly IVideoLoader[] VideoLoaders;
public readonly HotkeyManager Hotkeys;
public readonly Translation Translation;
public ILoadScreen LoadScreen { get; }
public CursorProvider CursorProvider { get; private set; }
public FS ModFiles;
@@ -102,8 +101,6 @@ namespace OpenRA
Hotkeys = new HotkeyManager(ModFiles, Game.Settings.Keys, Manifest);
Translation = new Translation(Game.Settings.Player.Language, Manifest.Translations, DefaultFileSystem);
defaultRules = Exts.Lazy(() => Ruleset.LoadDefaults(this));
defaultTerrainInfo = Exts.Lazy(() =>
{
@@ -137,6 +134,7 @@ namespace OpenRA
// horribly when you use ModData in unexpected ways.
ChromeMetrics.Initialize(this);
ChromeProvider.Initialize(this);
TranslationProvider.Initialize(this, fileSystem);
Game.Sound.Initialize(SoundLoaders, fileSystem);

View File

@@ -76,7 +76,7 @@ namespace OpenRA.Network
return arguments.ToArray();
}
public LocalizedMessage(ModData modData, MiniYaml yaml)
public LocalizedMessage(MiniYaml yaml)
{
// Let the FieldLoader do the dirty work of loading the public fields.
FieldLoader.Load(this, yaml);
@@ -95,7 +95,7 @@ namespace OpenRA.Network
argumentDictionary.Add(argument.Key, argument.Value);
}
TranslatedText = modData.Translation.GetString(Key, argumentDictionary);
TranslatedText = TranslationProvider.GetString(Key, argumentDictionary);
}
public static string Serialize(string key, Dictionary<string, object> arguments = null)

View File

@@ -43,7 +43,7 @@ namespace OpenRA.Network
var yaml = MiniYaml.FromString(order.TargetString);
foreach (var node in yaml)
{
var localizedMessage = new LocalizedMessage(Game.ModData, node.Value);
var localizedMessage = new LocalizedMessage(node.Value);
TextNotificationsManager.AddSystemLine(localizedMessage.TranslatedText);
}

View File

@@ -958,7 +958,7 @@ namespace OpenRA.Server
DispatchServerOrdersToClients(Order.FromTargetString("LocalizedMessage", text, true));
if (Type == ServerType.Dedicated)
WriteLineWithTimeStamp(ModData.Translation.GetString(key, arguments));
WriteLineWithTimeStamp(TranslationProvider.GetString(key, arguments));
}
public void SendLocalizedMessageTo(Connection conn, string key, Dictionary<string, object> arguments = null)
@@ -1312,7 +1312,7 @@ namespace OpenRA.Server
{
lock (LobbyInfo)
{
WriteLineWithTimeStamp(ModData.Translation.GetString(GameStarted));
WriteLineWithTimeStamp(TranslationProvider.GetString(GameStarted));
// Drop any players who are not ready
foreach (var c in Conns.Where(c => !c.Validated || GetClient(c).IsInvalid).ToArray())

View File

@@ -0,0 +1,76 @@
#region Copyright & License Information
/*
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System.Collections.Generic;
using OpenRA.FileSystem;
namespace OpenRA
{
public static class TranslationProvider
{
// Ensure thread-safety.
static readonly object SyncObject = new();
static Translation modTranslation;
static Translation mapTranslation;
public static void Initialize(ModData modData, IReadOnlyFileSystem fileSystem)
{
lock (SyncObject)
{
modTranslation = new Translation(Game.Settings.Player.Language, modData.Manifest.Translations, fileSystem);
mapTranslation = fileSystem is Map map && map.TranslationDefinitions != null
? new Translation(Game.Settings.Player.Language, FieldLoader.GetValue<string[]>("value", map.TranslationDefinitions.Value), fileSystem)
: null;
}
}
public static string GetString(string key, IDictionary<string, object> args = null)
{
lock (SyncObject)
{
// By prioritizing mod-level translations we prevent maps from overwriting translation keys. We do not want to
// allow maps to change the UI nor any other strings not exposed to the map.
if (modTranslation.TryGetString(key, out var message, args))
return message;
if (mapTranslation != null)
return mapTranslation.GetString(key, args);
return key;
}
}
public static bool TryGetString(string key, out string message, IDictionary<string, object> args = null)
{
lock (SyncObject)
{
// By prioritizing mod-level translations we prevent maps from overwriting translation keys. We do not want to
// allow maps to change the UI nor any other strings not exposed to the map.
if (modTranslation.TryGetString(key, out message, args))
return true;
if (mapTranslation != null && mapTranslation.TryGetString(key, out message, args))
return true;
return false;
}
}
/// <summary>Should only be used by <see cref="MapPreview"/>.</summary>
internal static bool TryGetModString(string key, out string message, IDictionary<string, object> args = null)
{
lock (SyncObject)
{
return modTranslation.TryGetString(key, out message, args);
}
}
}
}