Files
ichni_Official/Assets/Scripts/Localization/LocalizationTextService.cs
2026-07-24 17:56:30 -04:00

135 lines
5.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}");
}
}
}