Files
OpenRA/OpenRA.Game/FluentProvider.cs
let5sne.win10 9cf6ebb986
Some checks failed
Continuous Integration / Linux (.NET 8.0) (push) Has been cancelled
Continuous Integration / Windows (.NET 8.0) (push) Has been cancelled
Initial commit: OpenRA game engine
Fork from OpenRA/OpenRA with one-click launch script (start-ra.cmd)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 21:46:54 +08:00

95 lines
2.9 KiB
C#

#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;
using System.Collections.Immutable;
using System.Text;
using OpenRA.FileSystem;
namespace OpenRA
{
public static class FluentProvider
{
// Ensure thread-safety.
static readonly object SyncObject = new();
static FluentBundle modFluentBundle;
static FluentBundle mapFluentBundle;
public static void Initialize(Manifest manifest, IReadOnlyFileSystem fileSystem)
{
lock (SyncObject)
{
modFluentBundle = new FluentBundle(manifest.FluentCulture, manifest.FluentMessages, fileSystem);
if (fileSystem is Map map && map.FluentMessageDefinitions != null)
{
var files = ImmutableArray<string>.Empty;
if (map.FluentMessageDefinitions.Value != null)
files = FieldLoader.GetValue<ImmutableArray<string>>("value", map.FluentMessageDefinitions.Value);
string text = null;
if (map.FluentMessageDefinitions.Nodes.Length > 0)
{
var builder = new StringBuilder();
foreach (var node in map.FluentMessageDefinitions.Nodes)
if (node.Key == "base64")
builder.Append(Encoding.UTF8.GetString(Convert.FromBase64String(node.Value.Value)));
text = builder.ToString();
}
mapFluentBundle = new FluentBundle(manifest.FluentCulture, files, fileSystem, text);
}
}
}
public static string GetMessage(string key, params object[] args)
{
lock (SyncObject)
{
// By prioritizing mod-level fluent bundles we prevent maps from overwriting string keys. We do not want to
// allow maps to change the UI nor any other strings not exposed to the map.
if (modFluentBundle.TryGetMessage(key, out var message, args))
return message;
if (mapFluentBundle != null)
return mapFluentBundle.GetMessage(key, args);
return key;
}
}
public static bool TryGetMessage(string key, out string message, params object[] args)
{
lock (SyncObject)
{
// By prioritizing mod-level bundle we prevent maps from overwriting string keys. We do not want to
// allow maps to change the UI nor any other strings not exposed to the map.
if (modFluentBundle.TryGetMessage(key, out message, args))
return true;
if (mapFluentBundle != null && mapFluentBundle.TryGetMessage(key, out message, args))
return true;
return false;
}
}
/// <summary>Should only be used by <see cref="MapPreview"/>.</summary>
internal static bool TryGetModMessage(string key, out string message, params object[] args)
{
lock (SyncObject)
{
return modFluentBundle.TryGetMessage(key, out message, args);
}
}
}
}