mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
163 lines
6.2 KiB
C#
163 lines
6.2 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
using CheapLoc;
|
|
using Dalamud.Configuration.Internal;
|
|
using Serilog;
|
|
|
|
namespace Dalamud
|
|
{
|
|
/// <summary>
|
|
/// Class handling localization.
|
|
/// </summary>
|
|
[ServiceManager.EarlyLoadedService]
|
|
public class Localization : IServiceType
|
|
{
|
|
/// <summary>
|
|
/// Array of language codes which have a valid translation in Dalamud.
|
|
/// </summary>
|
|
public static readonly string[] ApplicableLangCodes = { "de", "ja", "fr", "it", "es", "ko", "no", "ru" };
|
|
|
|
private const string FallbackLangCode = "en";
|
|
|
|
private readonly string locResourceDirectory;
|
|
private readonly string locResourcePrefix;
|
|
private readonly bool useEmbedded;
|
|
private readonly Assembly assembly;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="Localization"/> class.
|
|
/// </summary>
|
|
/// <param name="locResourceDirectory">The working directory to load language files from.</param>
|
|
/// <param name="locResourcePrefix">The prefix on the loc resource file name (e.g. dalamud_).</param>
|
|
/// <param name="useEmbedded">Use embedded loc resource files.</param>
|
|
public Localization(string locResourceDirectory, string locResourcePrefix = "", bool useEmbedded = false)
|
|
{
|
|
this.locResourceDirectory = locResourceDirectory;
|
|
this.locResourcePrefix = locResourcePrefix;
|
|
this.useEmbedded = useEmbedded;
|
|
this.assembly = Assembly.GetCallingAssembly();
|
|
}
|
|
|
|
[ServiceManager.ServiceConstructor]
|
|
private Localization(Dalamud dalamud, DalamudConfiguration configuration)
|
|
: this(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "loc", "dalamud"), "dalamud_")
|
|
{
|
|
if (!string.IsNullOrEmpty(configuration.LanguageOverride))
|
|
this.SetupWithLangCode(configuration.LanguageOverride);
|
|
else
|
|
this.SetupWithUiCulture();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delegate for the <see cref="Localization.LocalizationChanged"/> event that occurs when the language is changed.
|
|
/// </summary>
|
|
/// <param name="langCode">The language code of the new language.</param>
|
|
public delegate void LocalizationChangedDelegate(string langCode);
|
|
|
|
/// <summary>
|
|
/// Event that occurs when the language is changed.
|
|
/// </summary>
|
|
public event LocalizationChangedDelegate LocalizationChanged;
|
|
|
|
/// <summary>
|
|
/// Search the set-up localization data for the provided assembly for the given string key and return it.
|
|
/// If the key is not present, the fallback is shown.
|
|
/// The fallback is also required to create the string files to be localized.
|
|
/// </summary>
|
|
/// <param name="key">The string key to be returned.</param>
|
|
/// <param name="fallBack">The fallback string, usually your source language.</param>
|
|
/// <returns>The localized string, fallback or string key if not found.</returns>
|
|
// TODO: This breaks loc export, since it's being called without string args. Fix in CheapLoc.
|
|
public static string Localize(string key, string fallBack)
|
|
{
|
|
return Loc.Localize(key, fallBack, Assembly.GetCallingAssembly());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set up the UI language with the users' local UI culture.
|
|
/// </summary>
|
|
public void SetupWithUiCulture()
|
|
{
|
|
try
|
|
{
|
|
var currentUiLang = CultureInfo.CurrentUICulture;
|
|
Log.Information("Trying to set up Loc for culture {0}", currentUiLang.TwoLetterISOLanguageName);
|
|
|
|
if (ApplicableLangCodes.Any(langCode => currentUiLang.TwoLetterISOLanguageName == langCode))
|
|
{
|
|
this.SetupWithLangCode(currentUiLang.TwoLetterISOLanguageName);
|
|
}
|
|
else
|
|
{
|
|
this.SetupWithFallbacks();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Could not get language information. Setting up fallbacks.");
|
|
this.SetupWithFallbacks();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set up the UI language with "fallbacks"(original English text).
|
|
/// </summary>
|
|
public void SetupWithFallbacks()
|
|
{
|
|
this.LocalizationChanged?.Invoke(FallbackLangCode);
|
|
Loc.SetupWithFallbacks(this.assembly);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set up the UI language with the provided language code.
|
|
/// </summary>
|
|
/// <param name="langCode">The language code to set up the UI language with.</param>
|
|
public void SetupWithLangCode(string langCode)
|
|
{
|
|
if (langCode.ToLower() == FallbackLangCode)
|
|
{
|
|
this.SetupWithFallbacks();
|
|
return;
|
|
}
|
|
|
|
this.LocalizationChanged?.Invoke(langCode);
|
|
|
|
try
|
|
{
|
|
Loc.Setup(this.ReadLocData(langCode), this.assembly);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Could not load loc {0}. Setting up fallbacks.", langCode);
|
|
this.SetupWithFallbacks();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves localizable JSON data in the current working directory for the provided assembly.
|
|
/// </summary>
|
|
public void ExportLocalizable()
|
|
{
|
|
Loc.ExportLocalizableForAssembly(this.assembly);
|
|
}
|
|
|
|
private string ReadLocData(string langCode)
|
|
{
|
|
if (this.useEmbedded)
|
|
{
|
|
var resourceStream = this.assembly.GetManifestResourceStream($"{this.locResourceDirectory}{this.locResourcePrefix}{langCode}.json");
|
|
if (resourceStream == null)
|
|
return null;
|
|
|
|
using var reader = new StreamReader(resourceStream);
|
|
return reader.ReadToEnd();
|
|
}
|
|
|
|
return File.ReadAllText(Path.Combine(this.locResourceDirectory, $"{this.locResourcePrefix}{langCode}.json"));
|
|
}
|
|
}
|
|
}
|