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
{
///
/// 项目运行时代码读取 Unity Localization 文本的统一入口。
/// 静态 Prefab 文本仍应使用 LocalizeStringEvent;只有运行时生成、Yarn 命令、Story 数据等无法直接挂组件的文本才调用本服务。
/// 同步接口绝不强制 Addressables 完成加载:Localization 尚未就绪时直接返回 fallback,避免在场景切换或 UI 点击中制造卡顿。
///
public static class LocalizationTextService
{
private static readonly HashSet ReportedFallbacks = new HashSet();
///
/// 在 Unity Localization 已初始化时立即解析文本;无法解析时返回调用方提供的 fallback。
/// fallback 传入 null 时回退显示 Key,适合开发阶段快速定位缺失条目;传入空字符串时会保留空字符串。
///
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 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;
}
///
/// 异步解析文本。该接口只等待 Unity 官方 和字符串加载操作,
/// 不创建额外 Bootstrap,也不使用 WaitForCompletion 阻塞主线程。
///
public static async Task ResolveAsync(
TableReference tableReference,
string entryKey,
string fallback = null,
params object[] arguments)
{
string resolvedFallback = GetFallback(entryKey, fallback);
if (string.IsNullOrEmpty(entryKey))
{
return resolvedFallback;
}
try
{
AsyncOperationHandle initializationOperation = LocalizationSettings.InitializationOperation;
await initializationOperation.Task;
if (initializationOperation.Status != AsyncOperationStatus.Succeeded)
{
ReportFallbackOnce(tableReference, entryKey, "Unity Localization 初始化失败");
return resolvedFallback;
}
AsyncOperationHandle 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;
}
///
/// 同一 Table/Key 的回退原因只输出一次,避免 Helper、Timeline 等重复刷新 UI 时刷屏。
///
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}");
}
}
}