Fix translation container loading with resource/db fallbacks
This commit is contained in:
parent
a24f562e30
commit
3f47ae7cb3
3 changed files with 159 additions and 14 deletions
|
|
@ -427,10 +427,16 @@ services:
|
||||||
REDIS_PORT: 6379
|
REDIS_PORT: 6379
|
||||||
MQTT_BROKER_ADDRESS: mqtt
|
MQTT_BROKER_ADDRESS: mqtt
|
||||||
MQTT_BROKER_PORT: 1883
|
MQTT_BROKER_PORT: 1883
|
||||||
|
DATABASE_IP: postgres
|
||||||
|
DATABASE_PORT: 5432
|
||||||
|
DATABASE_NAME: game
|
||||||
|
DATABASE_USER: ${POSTGRES_USER}
|
||||||
|
DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
Logging__LogLevel__Microsoft.AspNetCore.Server.Kestrel: Error
|
Logging__LogLevel__Microsoft.AspNetCore.Server.Kestrel: Error
|
||||||
command: ["/app/TranslationsServer.dll"]
|
command: ["/app/TranslationsServer.dll"]
|
||||||
volumes:
|
volumes:
|
||||||
- ./translations:/app/translations:ro
|
- ./translations:/app/translations
|
||||||
|
- ./resources:/app/resources:ro
|
||||||
ports:
|
ports:
|
||||||
- "19999:19999"
|
- "19999:19999"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Npgsql;
|
||||||
using PhoenixLib.Logging;
|
using PhoenixLib.Logging;
|
||||||
using PhoenixLib.MultiLanguage;
|
using PhoenixLib.MultiLanguage;
|
||||||
using WingsAPI.Data.GameData;
|
using WingsAPI.Data.GameData;
|
||||||
|
|
@ -41,7 +43,13 @@ namespace TranslationServer.Loader
|
||||||
var newTmp = new Dictionary<string, string>();
|
var newTmp = new Dictionary<string, string>();
|
||||||
|
|
||||||
string languageDirectory = Path.Combine(_options.TranslationsPath, $"{languageType}");
|
string languageDirectory = Path.Combine(_options.TranslationsPath, $"{languageType}");
|
||||||
foreach (string translationFile in Directory.GetFiles(languageDirectory, "*.yml").Concat(Directory.GetFiles(languageDirectory, "*.yaml")))
|
IEnumerable<string> translationFiles = Enumerable.Empty<string>();
|
||||||
|
if (Directory.Exists(languageDirectory))
|
||||||
|
{
|
||||||
|
translationFiles = Directory.GetFiles(languageDirectory, "*.yml").Concat(Directory.GetFiles(languageDirectory, "*.yaml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string translationFile in translationFiles)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -64,28 +72,158 @@ namespace TranslationServer.Loader
|
||||||
|
|
||||||
newTmp[s] = value;
|
newTmp[s] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == RegionLanguageType.EN)
|
|
||||||
{
|
|
||||||
english = newTmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
_translations.AddRange(newTmp.Select(s => new GenericTranslationDto
|
|
||||||
{
|
|
||||||
Key = s.Key,
|
|
||||||
Value = s.Value,
|
|
||||||
Language = i
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error($"[RESOURCE_LOADER] {translationFile} {languageType}", e);
|
Log.Error($"[RESOURCE_LOADER] {translationFile} {languageType}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!newTmp.Any())
|
||||||
|
{
|
||||||
|
foreach ((string key, string value) in LoadFromResourceLangFiles(i))
|
||||||
|
{
|
||||||
|
newTmp[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newTmp.Any())
|
||||||
|
{
|
||||||
|
foreach ((string key, string value) in LoadFromDatabaseLangFiles(i))
|
||||||
|
{
|
||||||
|
newTmp[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == RegionLanguageType.EN)
|
||||||
|
{
|
||||||
|
english = newTmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
_translations.AddRange(newTmp.Select(s => new GenericTranslationDto
|
||||||
|
{
|
||||||
|
Key = s.Key,
|
||||||
|
Value = s.Value,
|
||||||
|
Language = i
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Info($"[RESOURCE_LOADER] {_translations.Count.ToString()} translations loaded");
|
Log.Info($"[RESOURCE_LOADER] {_translations.Count.ToString()} translations loaded");
|
||||||
return _translations;
|
return _translations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<(string key, string value)> LoadFromResourceLangFiles(RegionLanguageType lang)
|
||||||
|
{
|
||||||
|
var entries = new List<(string key, string value)>();
|
||||||
|
string marker = lang switch
|
||||||
|
{
|
||||||
|
RegionLanguageType.EN => "_uk_",
|
||||||
|
RegionLanguageType.DE => "_de_",
|
||||||
|
RegionLanguageType.FR => "_fr_",
|
||||||
|
RegionLanguageType.IT => "_it_",
|
||||||
|
RegionLanguageType.ES => "_es_",
|
||||||
|
RegionLanguageType.CZ => "_cz_",
|
||||||
|
RegionLanguageType.PL => "_pl_",
|
||||||
|
RegionLanguageType.TR => "_tr_",
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (marker == null)
|
||||||
|
{
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const string resourceLangPath = "/app/resources/lang";
|
||||||
|
if (!Directory.Exists(resourceLangPath))
|
||||||
|
{
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(resourceLangPath, $"*{marker}*.txt", SearchOption.TopDirectoryOnly))
|
||||||
|
{
|
||||||
|
string filePrefix = Path.GetFileNameWithoutExtension(file)?.Replace('.', '_') ?? "lang";
|
||||||
|
foreach (string line in File.ReadAllLines(file, Encoding.Latin1))
|
||||||
|
{
|
||||||
|
string[] parts = line.Split('\t');
|
||||||
|
if (parts.Length < 2 || string.IsNullOrWhiteSpace(parts[0]) || string.IsNullOrWhiteSpace(parts[1]))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.Add(($"{filePrefix}.{parts[0]}", parts[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error($"[RESOURCE_LOADER] Resource language fallback failed for {lang}", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<(string key, string value)> LoadFromDatabaseLangFiles(RegionLanguageType lang)
|
||||||
|
{
|
||||||
|
var entries = new List<(string key, string value)>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string marker = lang switch
|
||||||
|
{
|
||||||
|
RegionLanguageType.EN => "_uk_",
|
||||||
|
RegionLanguageType.DE => "_de_",
|
||||||
|
RegionLanguageType.FR => "_fr_",
|
||||||
|
RegionLanguageType.IT => "_it_",
|
||||||
|
RegionLanguageType.ES => "_es_",
|
||||||
|
RegionLanguageType.CZ => "_cz_",
|
||||||
|
RegionLanguageType.PL => "_pl_",
|
||||||
|
RegionLanguageType.TR => "_tr_",
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (marker == null)
|
||||||
|
{
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
string host = Environment.GetEnvironmentVariable("DATABASE_IP") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_IP") ?? "127.0.0.1";
|
||||||
|
string port = Environment.GetEnvironmentVariable("DATABASE_PORT") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PORT") ?? "5432";
|
||||||
|
string db = Environment.GetEnvironmentVariable("DATABASE_NAME") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_NAME") ?? "game";
|
||||||
|
string user = Environment.GetEnvironmentVariable("DATABASE_USER") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_USER") ?? "postgres";
|
||||||
|
string pass = Environment.GetEnvironmentVariable("DATABASE_PASSWORD") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PASSWORD") ?? "postgres";
|
||||||
|
|
||||||
|
using var conn = new NpgsqlConnection($"Host={host};Port={port};Database={db};Username={user};Password={pass}");
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
using var cmd = new NpgsqlCommand("SELECT relative_path, content FROM resources.resource_files WHERE category='lang' AND lower(relative_path) LIKE lower(@needle);", conn);
|
||||||
|
cmd.Parameters.AddWithValue("needle", $"%{marker}%");
|
||||||
|
using var reader = cmd.ExecuteReader();
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
string path = reader.GetString(0);
|
||||||
|
string filePrefix = Path.GetFileNameWithoutExtension(path)?.Replace('.', '_') ?? "lang";
|
||||||
|
byte[] content = (byte[])reader[1];
|
||||||
|
string text = Encoding.Latin1.GetString(content);
|
||||||
|
foreach (string line in text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
string[] parts = line.Split('\t');
|
||||||
|
if (parts.Length < 2 || string.IsNullOrWhiteSpace(parts[0]) || string.IsNullOrWhiteSpace(parts[1]))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string key = $"{filePrefix}.{parts[0]}";
|
||||||
|
entries.Add((key, parts[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error($"[RESOURCE_LOADER] DB language fallback failed for {lang}", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Npgsql" Version="5.0.18" />
|
||||||
<PackageReference Include="protobuf-net.Grpc" Version="1.0.152" />
|
<PackageReference Include="protobuf-net.Grpc" Version="1.0.152" />
|
||||||
<PackageReference Include="protobuf-net.Grpc.AspNetCore" Version="1.0.152" />
|
<PackageReference Include="protobuf-net.Grpc.AspNetCore" Version="1.0.152" />
|
||||||
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue