2026-03-31 19:06:40 +08:00
|
|
|
|
using System.Collections.Generic;
|
2026-03-31 17:25:20 +08:00
|
|
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
|
|
using AlicizaX.Resource.Runtime;
|
|
|
|
|
|
using UnityEngine;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
|
|
|
|
|
|
namespace AlicizaX.Localization.Runtime
|
|
|
|
|
|
{
|
2026-03-31 19:06:40 +08:00
|
|
|
|
|
2025-09-05 19:46:30 +08:00
|
|
|
|
[DisallowMultipleComponent]
|
|
|
|
|
|
[AddComponentMenu("Game Framework/Localization")]
|
|
|
|
|
|
public sealed class LocalizationComponent : MonoBehaviour
|
|
|
|
|
|
{
|
2026-03-31 17:25:20 +08:00
|
|
|
|
private const string DefaultLanguage = "ChineseSimplified";
|
|
|
|
|
|
private const string RuntimeLanguagePrefsKey = "AlicizaX.Localization.Language";
|
|
|
|
|
|
|
2026-03-26 16:14:05 +08:00
|
|
|
|
private ILocalizationService _mLocalizationService = null;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
|
|
|
|
|
|
public static string PrefsKey = Application.dataPath.GetHashCode() + "Language";
|
|
|
|
|
|
|
2025-10-11 15:18:09 +08:00
|
|
|
|
[SerializeField] private string _language;
|
2026-03-31 17:25:20 +08:00
|
|
|
|
[SerializeField] private List<GameLocaizationTable> _startupTables = new();
|
|
|
|
|
|
[SerializeField] private List<string> _startupTableLocations = new();
|
|
|
|
|
|
[SerializeField] private string _resourcePackageName = string.Empty;
|
2025-10-11 15:18:09 +08:00
|
|
|
|
|
2026-03-10 13:48:17 +08:00
|
|
|
|
internal void SetLanguage(string language)
|
2025-10-11 15:18:09 +08:00
|
|
|
|
{
|
|
|
|
|
|
_language = language;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-31 17:25:20 +08:00
|
|
|
|
internal static void SaveLanguagePreference(string language)
|
2025-09-05 19:46:30 +08:00
|
|
|
|
{
|
2026-03-31 17:25:20 +08:00
|
|
|
|
if (string.IsNullOrEmpty(language))
|
2025-09-05 19:46:30 +08:00
|
|
|
|
{
|
2026-03-31 17:25:20 +08:00
|
|
|
|
return;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
2026-03-31 17:25:20 +08:00
|
|
|
|
|
2025-10-11 15:18:09 +08:00
|
|
|
|
#if UNITY_EDITOR
|
2026-03-31 17:25:20 +08:00
|
|
|
|
UnityEditor.EditorPrefs.SetString(PrefsKey, language);
|
2025-10-11 15:18:09 +08:00
|
|
|
|
#endif
|
2026-03-31 17:25:20 +08:00
|
|
|
|
PlayerPrefs.SetString(RuntimeLanguagePrefsKey, language);
|
|
|
|
|
|
PlayerPrefs.Save();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static string LoadLanguagePreference(string fallbackLanguage)
|
|
|
|
|
|
{
|
|
|
|
|
|
string fallback = string.IsNullOrEmpty(fallbackLanguage) ? DefaultLanguage : fallbackLanguage;
|
|
|
|
|
|
string language = PlayerPrefs.GetString(RuntimeLanguagePrefsKey, fallback);
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
|
language = UnityEditor.EditorPrefs.GetString(PrefsKey, language);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
return string.IsNullOrEmpty(language) ? fallback : language;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-31 19:06:40 +08:00
|
|
|
|
private void Start()
|
2026-03-31 17:25:20 +08:00
|
|
|
|
{
|
2026-04-20 13:46:44 +08:00
|
|
|
|
if (!AppServices.TryGetApp<ILocalizationService>(out _mLocalizationService))
|
2026-03-31 17:25:20 +08:00
|
|
|
|
{
|
2026-04-20 13:46:44 +08:00
|
|
|
|
_mLocalizationService = AppServices.RegisterApp(new LocalizationService());
|
2026-03-31 17:25:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_mLocalizationService == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Log.Info("Localization manager is invalid.");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_language = LoadLanguagePreference(_language);
|
2026-03-26 16:14:05 +08:00
|
|
|
|
_mLocalizationService.Initialize(_language);
|
2026-03-31 17:25:20 +08:00
|
|
|
|
ApplyStartupTables(_startupTables);
|
|
|
|
|
|
|
|
|
|
|
|
if (_startupTableLocations != null && _startupTableLocations.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadStartupTablesAsync().Forget();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ApplyStartupTables(List<GameLocaizationTable> tables)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tables == null || tables.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool applied = false;
|
|
|
|
|
|
for (int i = 0; i < tables.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameLocaizationTable table = tables[i];
|
|
|
|
|
|
if (table == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!applied)
|
|
|
|
|
|
{
|
|
|
|
|
|
_mLocalizationService.CoverAddLocalizationConfig(table);
|
|
|
|
|
|
applied = true;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_mLocalizationService.IncreAddLocalizationConfig(table);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async UniTaskVoid LoadStartupTablesAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!AppServices.TryGet<IResourceService>(out var resourceService))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
List<GameLocaizationTable> loadedTables = new(_startupTableLocations.Count);
|
|
|
|
|
|
for (int i = 0; i < _startupTableLocations.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
string location = _startupTableLocations[i];
|
|
|
|
|
|
if (string.IsNullOrEmpty(location))
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GameLocaizationTable table = await resourceService.LoadAssetAsync<GameLocaizationTable>(location, default, _resourcePackageName);
|
|
|
|
|
|
if (table != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
loadedTables.Add(table);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (loadedTables.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_startupTables == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_startupTables = new List<GameLocaizationTable>(loadedTables.Count);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < loadedTables.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameLocaizationTable table = loadedTables[i];
|
|
|
|
|
|
if (_startupTables.Contains(table))
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_startupTables.Add(table);
|
|
|
|
|
|
_mLocalizationService.IncreAddLocalizationConfig(table);
|
|
|
|
|
|
}
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|