feat: 本地化字体兼容
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AibisDream.Utility;
|
||||
using UnityEngine;
|
||||
@@ -11,22 +12,14 @@ using UnityEditor;
|
||||
|
||||
namespace AibisDream.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// csv 本地化列类别。集中声明"哪些 Locale 归到哪一列",csv 数据类按此枚举取字段。
|
||||
/// </summary>
|
||||
public enum LocaleKind
|
||||
{
|
||||
Cn,
|
||||
En,
|
||||
Ja,
|
||||
Ru,
|
||||
Es,
|
||||
PtBr
|
||||
}
|
||||
|
||||
public static class LocalizationKit
|
||||
{
|
||||
private const string LocalizationPrefix = "l10n.";
|
||||
private static Task<bool> currentLanguageSwitchTask;
|
||||
private static int languageSwitchVersion;
|
||||
private static bool managedLocaleChange;
|
||||
private static bool typographyLoaderConfigured;
|
||||
private static bool localeChangedSubscribed;
|
||||
|
||||
public static string CurrentLanguageCode { get; private set; } = "zh-Hans";
|
||||
public static Locale CurrentLocale => LocalizationSettings.SelectedLocale;
|
||||
@@ -78,8 +71,14 @@ namespace AibisDream.Framework
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.playModeStateChanged += OnPlayModeChanged;
|
||||
if (EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
EnsureTypographyLoaderConfigured();
|
||||
SubscribeLocaleChanged();
|
||||
RefreshCurrentLanguageCodeAsync();
|
||||
}
|
||||
#else
|
||||
LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged;
|
||||
SubscribeLocaleChanged();
|
||||
RefreshCurrentLanguageCodeAsync();
|
||||
#endif
|
||||
}
|
||||
@@ -88,6 +87,14 @@ namespace AibisDream.Framework
|
||||
{
|
||||
UpdateCurrentLanguageCode(locale);
|
||||
EnumEventSystem.Global.Send(SettingChangeEvent.LocaleChanged, locale);
|
||||
|
||||
if (!managedLocaleChange && locale != null)
|
||||
{
|
||||
EnsureTypographyLoaderConfigured();
|
||||
LocaleKind localeKind = GetLocaleKind(locale.Identifier.Code);
|
||||
if (!TypographyService.IsActiveFor(localeKind))
|
||||
currentLanguageSwitchTask = TypographyService.LoadAndActivateAsync(localeKind);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateCurrentLanguageCode(Locale locale)
|
||||
@@ -109,32 +116,95 @@ namespace AibisDream.Framework
|
||||
{
|
||||
if (playMode == PlayModeStateChange.EnteredPlayMode)
|
||||
{
|
||||
LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged;
|
||||
EnsureTypographyLoaderConfigured();
|
||||
SubscribeLocaleChanged();
|
||||
RefreshCurrentLanguageCodeAsync();
|
||||
}
|
||||
else if (playMode == PlayModeStateChange.ExitingPlayMode)
|
||||
{
|
||||
LocalizationSettings.SelectedLocaleChanged -= OnLocaleChanged;
|
||||
UnsubscribeLocaleChanged();
|
||||
TypographyService.ResetForTests();
|
||||
typographyLoaderConfigured = false;
|
||||
currentLanguageSwitchTask = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static async void SwitchLanguage(string localeCode)
|
||||
public static void SwitchLanguage(string localeCode)
|
||||
{
|
||||
_ = SwitchLanguageAsync(localeCode);
|
||||
}
|
||||
|
||||
public static Task<bool> SwitchLanguageAsync(string localeCode)
|
||||
{
|
||||
int requestVersion = Interlocked.Increment(ref languageSwitchVersion);
|
||||
currentLanguageSwitchTask = SwitchLanguageCoreAsync(localeCode, requestVersion);
|
||||
return currentLanguageSwitchTask;
|
||||
}
|
||||
|
||||
private static async Task<bool> SwitchLanguageCoreAsync(string localeCode, int requestVersion)
|
||||
{
|
||||
// 等待本地化系统初始化完成
|
||||
await LocalizationSettings.InitializationOperation.Task;
|
||||
|
||||
var selectedLocale =
|
||||
LocalizationSettings.AvailableLocales.Locales.Find(locale => locale.Identifier.Code == localeCode);
|
||||
if (!selectedLocale)
|
||||
{
|
||||
Debug.LogWarning($"Locale with code {localeCode} not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedLocale)
|
||||
EnsureTypographyLoaderConfigured();
|
||||
bool typographyReady = await TypographyService.LoadAndActivateAsync(GetLocaleKind(localeCode));
|
||||
if (requestVersion != languageSwitchVersion)
|
||||
return false;
|
||||
|
||||
managedLocaleChange = true;
|
||||
try
|
||||
{
|
||||
LocalizationSettings.SelectedLocale = selectedLocale;
|
||||
}
|
||||
else
|
||||
finally
|
||||
{
|
||||
Debug.LogWarning($"Locale with code {localeCode} not found.");
|
||||
managedLocaleChange = false;
|
||||
}
|
||||
|
||||
await Task.Yield();
|
||||
Canvas.ForceUpdateCanvases();
|
||||
if (!typographyReady)
|
||||
{
|
||||
Debug.LogWarning(
|
||||
$"[LocalizationKit] Locale 已切换为 {localeCode},但字体 Profile 加载失败,保留上一套字体。");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void EnsureTypographyLoaderConfigured()
|
||||
{
|
||||
if (typographyLoaderConfigured)
|
||||
return;
|
||||
|
||||
TypographyService.ConfigureLoader(new ResourceSystemTypographyProfileLoader());
|
||||
typographyLoaderConfigured = true;
|
||||
}
|
||||
|
||||
private static void SubscribeLocaleChanged()
|
||||
{
|
||||
if (localeChangedSubscribed)
|
||||
return;
|
||||
|
||||
LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged;
|
||||
localeChangedSubscribed = true;
|
||||
}
|
||||
|
||||
private static void UnsubscribeLocaleChanged()
|
||||
{
|
||||
if (!localeChangedSubscribed)
|
||||
return;
|
||||
|
||||
LocalizationSettings.SelectedLocaleChanged -= OnLocaleChanged;
|
||||
localeChangedSubscribed = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -250,6 +320,24 @@ namespace AibisDream.Framework
|
||||
public static IEnumerator WaitUntilReady()
|
||||
{
|
||||
yield return LocalizationSettings.InitializationOperation;
|
||||
|
||||
Task<bool> languageTask;
|
||||
do
|
||||
{
|
||||
languageTask = currentLanguageSwitchTask;
|
||||
while (languageTask != null && !languageTask.IsCompleted)
|
||||
yield return null;
|
||||
} while (languageTask != currentLanguageSwitchTask);
|
||||
|
||||
EnsureTypographyLoaderConfigured();
|
||||
if (!TypographyService.IsReady)
|
||||
{
|
||||
Task<bool> typographyTask = TypographyService.LoadAndActivateAsync(
|
||||
GetLocaleKind(LocalizationSettings.SelectedLocale?.Identifier.Code));
|
||||
while (!typographyTask.IsCompleted)
|
||||
yield return null;
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
namespace AibisDream.Framework
|
||||
{
|
||||
internal sealed class ResourceSystemTypographyProfileLoader : ITypographyProfileLoader
|
||||
{
|
||||
public async Task<TypographyProfile> LoadAsync(string key)
|
||||
{
|
||||
AsyncOperationHandle<TypographyProfile> handle =
|
||||
ResourceSystem.LoadPersistentAsync<TypographyProfile>(key);
|
||||
try
|
||||
{
|
||||
await handle.Task;
|
||||
if (handle.Status == AsyncOperationStatus.Succeeded && handle.Result != null)
|
||||
return handle.Result;
|
||||
|
||||
ResourceSystem.EarlyReleasePersistent(key);
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
ResourceSystem.EarlyReleasePersistent(key);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Release(string key)
|
||||
{
|
||||
ResourceSystem.EarlyReleasePersistent(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9dd51810ef0cc94398175f3597a978e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -140,6 +140,15 @@ namespace AibisDream.Framework
|
||||
public static void EarlyRelease<T>(AsyncOperationHandle<T> handle)
|
||||
=> ActiveLoader.EarlyRelease(handle);
|
||||
|
||||
/// <summary>
|
||||
/// 提前释放持久化 Loader 中指定 Key 的资源。
|
||||
/// </summary>
|
||||
public static void EarlyReleasePersistent(string key)
|
||||
{
|
||||
if (_persistentLoader != null)
|
||||
_persistentLoader.EarlyRelease(key);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user