Browse Source

add json and resx localization managers

pull/2211/head
Cenngo 3 years ago
parent
commit
e54cf09f25
6 changed files with 132 additions and 0 deletions
  1. +12
    -0
      src/Discord.Net.Interactions/ILocalizationManager.cs
  2. +2
    -0
      src/Discord.Net.Interactions/InteractionService.cs
  3. +2
    -0
      src/Discord.Net.Interactions/InteractionServiceConfig.cs
  4. +59
    -0
      src/Discord.Net.Interactions/LocalizationManagers/JsonLocalizationManager.cs
  5. +47
    -0
      src/Discord.Net.Interactions/LocalizationManagers/ResxLocalizationManager.cs
  6. +10
    -0
      src/Discord.Net.Interactions/LocalizationTarget.cs

+ 12
- 0
src/Discord.Net.Interactions/ILocalizationManager.cs View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Discord.Interactions
{
public interface ILocalizationManager
{
Task<IDictionary<string, string>> GetAllNamesAsync(IList<string> key, LocalizationTarget destinationType, IServiceProvider serviceProvider);
Task<IDictionary<string, string>> GetAllDescriptionsAsync(IList<string> key, LocalizationTarget destinationType, IServiceProvider serviceProvider);
}
}

+ 2
- 0
src/Discord.Net.Interactions/InteractionService.cs View File

@@ -81,6 +81,7 @@ namespace Discord.Interactions
internal readonly string _wildCardExp;
internal readonly RunMode _runMode;
internal readonly RestResponseCallback _restResponseCallback;
internal readonly ILocalizationManager _localizationManager;

/// <summary>
/// Rest client to be used to register application commands.
@@ -180,6 +181,7 @@ namespace Discord.Interactions
_enableAutocompleteHandlers = config.EnableAutocompleteHandlers;
_autoServiceScopes = config.AutoServiceScopes;
_restResponseCallback = config.RestResponseCallback;
_localizationManager = config.LocalizationManager;

_typeConverterMap = new TypeMap<TypeConverter, IApplicationCommandInteractionDataOption>(this, new ConcurrentDictionary<Type, TypeConverter>
{


+ 2
- 0
src/Discord.Net.Interactions/InteractionServiceConfig.cs View File

@@ -64,6 +64,8 @@ namespace Discord.Interactions
/// Gets or sets whether a command execution should exit when a modal command encounters a missing modal component value.
/// </summary>
public bool ExitOnMissingModalField { get; set; } = false;

public ILocalizationManager LocalizationManager { get; set; }
}

/// <summary>


+ 59
- 0
src/Discord.Net.Interactions/LocalizationManagers/JsonLocalizationManager.cs View File

@@ -0,0 +1,59 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Discord.Interactions
{
internal class JsonLocalizationManager : ILocalizationManager
{
private const string NameIdentifier = "name";
private const string DescriptionIdentifier = "description";

private readonly string _basePath;
private readonly string _fileName;
private readonly Regex _localeParserRegex = new Regex(@"\w+.(?<locale>\w{2}-\w{2}).json", RegexOptions.Compiled | RegexOptions.Singleline);

public JsonLocalizationManager(string basePath, string fileName)
{
_basePath = basePath;
_fileName = fileName;
}

public Task<IDictionary<string, string>> GetAllDescriptionsAsync(IList<string> key, LocalizationTarget destinationType, IServiceProvider serviceProvider) =>
GetValuesAsync(key, DescriptionIdentifier);

public Task<IDictionary<string, string>> GetAllNamesAsync(IList<string> key, LocalizationTarget destinationType, IServiceProvider serviceProvider) =>
GetValuesAsync(key, NameIdentifier);

private string[] GetAllFiles() =>
Directory.GetFiles(_basePath, $"{_fileName}.*.json", SearchOption.TopDirectoryOnly);

private async Task<IDictionary<string, string>> GetValuesAsync(IList<string> key, string identifier)
{
var result = new Dictionary<string, string>();
var files = GetAllFiles();

foreach (var file in files)
{
var match = _localeParserRegex.Match(Path.GetFileName(file));
if (!match.Success)
continue;

var locale = match.Groups["locale"].Value;

using var sr = new StreamReader(file);
using var jr = new JsonTextReader(sr);
var obj = await JObject.LoadAsync(jr);
var token = string.Join(".", key) + $".{identifier}";
var value = (string)obj.SelectToken(token);
result[locale] = value;
}

return result;
}
}
}

+ 47
- 0
src/Discord.Net.Interactions/LocalizationManagers/ResxLocalizationManager.cs View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Threading.Tasks;

namespace Discord.Interactions
{
internal sealed class ResxLocalizationManager : ILocalizationManager
{
private const string NameIdentifier = "name";
private const string DescriptionIdentifier = "description";

private readonly string _baseResource;
private readonly Assembly _assembly;
private readonly ConcurrentDictionary<string, ResourceManager> _localizerCache = new();
private readonly IEnumerable<CultureInfo> _supportedLocales;

public ResxLocalizationManager(string baseResource, Assembly assembly, params CultureInfo[] supportedLocales)
{
_baseResource = baseResource;
_assembly = assembly;
_supportedLocales = supportedLocales;
}

public Task<IDictionary<string, string>> GetAllDescriptionsAsync(IList<string> key, LocalizationTarget destinationType, IServiceProvider serviceProvider) =>
Task.FromResult(GetValues(key, DescriptionIdentifier));

public Task<IDictionary<string, string>> GetAllNamesAsync(IList<string> key, LocalizationTarget destinationType, IServiceProvider serviceProvider) =>
Task.FromResult(GetValues(key, NameIdentifier));

private IDictionary<string, string> GetValues(IList<string> key, string identifier)
{
var result = new Dictionary<string, string>();

var resourceName = _baseResource + "." + string.Join(".", key);
var resourceManager = _localizerCache.GetOrAdd(resourceName, new ResourceManager(resourceName, _assembly));

foreach (var locale in _supportedLocales)
result[locale.Name] = resourceManager.GetString(identifier, locale);

return result;
}
}
}

+ 10
- 0
src/Discord.Net.Interactions/LocalizationTarget.cs View File

@@ -0,0 +1,10 @@
namespace Discord.Interactions
{
public enum LocalizationTarget
{
Group,
Command,
Parameter,
Choice
}
}

Loading…
Cancel
Save