135 lines
5.5 KiB
C#
135 lines
5.5 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
using UnityEngine;
|
||
using UnityEngine.Localization;
|
||
using UnityEngine.Localization.Settings;
|
||
using UnityEngine.Localization.Tables;
|
||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||
|
||
namespace Ichni.Localization
|
||
{
|
||
/// <summary>
|
||
/// 项目运行时代码读取 Unity Localization 文本的统一入口。
|
||
/// <para>静态 Prefab 文本仍应使用 <c>LocalizeStringEvent</c>;只有运行时生成、Yarn 命令、Story 数据等无法直接挂组件的文本才调用本服务。</para>
|
||
/// <para>同步接口绝不强制 Addressables 完成加载:Localization 尚未就绪时直接返回 fallback,避免在场景切换或 UI 点击中制造卡顿。</para>
|
||
/// </summary>
|
||
public static class LocalizationTextService
|
||
{
|
||
private static readonly HashSet<string> ReportedFallbacks = new HashSet<string>();
|
||
|
||
/// <summary>
|
||
/// 在 Unity Localization 已初始化时立即解析文本;无法解析时返回调用方提供的 fallback。
|
||
/// <para>fallback 传入 <c>null</c> 时回退显示 Key,适合开发阶段快速定位缺失条目;传入空字符串时会保留空字符串。</para>
|
||
/// </summary>
|
||
public static string Resolve(
|
||
TableReference tableReference,
|
||
string entryKey,
|
||
string fallback = null,
|
||
params object[] arguments)
|
||
{
|
||
string resolvedFallback = GetFallback(entryKey, fallback);
|
||
if (string.IsNullOrEmpty(entryKey))
|
||
{
|
||
return resolvedFallback;
|
||
}
|
||
|
||
AsyncOperationHandle<LocalizationSettings> initializationOperation = LocalizationSettings.InitializationOperation;
|
||
if (!initializationOperation.IsDone || initializationOperation.Status != AsyncOperationStatus.Succeeded)
|
||
{
|
||
ReportFallbackOnce(tableReference, entryKey, "Unity Localization 尚未完成初始化");
|
||
return resolvedFallback;
|
||
}
|
||
|
||
try
|
||
{
|
||
string localizedText = LocalizationSettings.StringDatabase.GetLocalizedString(
|
||
tableReference,
|
||
entryKey,
|
||
null,
|
||
FallbackBehavior.UseProjectSettings,
|
||
arguments);
|
||
if (!string.IsNullOrEmpty(localizedText))
|
||
{
|
||
return localizedText;
|
||
}
|
||
|
||
ReportFallbackOnce(tableReference, entryKey, "String Table 未返回有效文本");
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
ReportFallbackOnce(tableReference, entryKey, exception.Message);
|
||
}
|
||
|
||
return resolvedFallback;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 异步解析文本。该接口只等待 Unity 官方 <see cref="LocalizationSettings.InitializationOperation"/> 和字符串加载操作,
|
||
/// 不创建额外 Bootstrap,也不使用 <c>WaitForCompletion</c> 阻塞主线程。
|
||
/// </summary>
|
||
public static async Task<string> ResolveAsync(
|
||
TableReference tableReference,
|
||
string entryKey,
|
||
string fallback = null,
|
||
params object[] arguments)
|
||
{
|
||
string resolvedFallback = GetFallback(entryKey, fallback);
|
||
if (string.IsNullOrEmpty(entryKey))
|
||
{
|
||
return resolvedFallback;
|
||
}
|
||
|
||
try
|
||
{
|
||
AsyncOperationHandle<LocalizationSettings> initializationOperation = LocalizationSettings.InitializationOperation;
|
||
await initializationOperation.Task;
|
||
if (initializationOperation.Status != AsyncOperationStatus.Succeeded)
|
||
{
|
||
ReportFallbackOnce(tableReference, entryKey, "Unity Localization 初始化失败");
|
||
return resolvedFallback;
|
||
}
|
||
|
||
AsyncOperationHandle<string> textOperation = LocalizationSettings.StringDatabase.GetLocalizedStringAsync(
|
||
tableReference,
|
||
entryKey,
|
||
null,
|
||
FallbackBehavior.UseProjectSettings,
|
||
arguments);
|
||
await textOperation.Task;
|
||
if (textOperation.Status == AsyncOperationStatus.Succeeded && !string.IsNullOrEmpty(textOperation.Result))
|
||
{
|
||
return textOperation.Result;
|
||
}
|
||
|
||
ReportFallbackOnce(tableReference, entryKey, "String Table 异步加载失败或未返回有效文本");
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
ReportFallbackOnce(tableReference, entryKey, exception.Message);
|
||
}
|
||
|
||
return resolvedFallback;
|
||
}
|
||
|
||
private static string GetFallback(string entryKey, string fallback)
|
||
{
|
||
return fallback ?? entryKey ?? string.Empty;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同一 Table/Key 的回退原因只输出一次,避免 Helper、Timeline 等重复刷新 UI 时刷屏。
|
||
/// </summary>
|
||
private static void ReportFallbackOnce(TableReference tableReference, string entryKey, string reason)
|
||
{
|
||
string diagnosticKey = $"{tableReference}:{entryKey}";
|
||
if (!ReportedFallbacks.Add(diagnosticKey))
|
||
{
|
||
return;
|
||
}
|
||
|
||
Debug.LogWarning($"[LocalizationTextService] 无法解析 '{diagnosticKey}',将显示 fallback。原因:{reason}");
|
||
}
|
||
}
|
||
}
|