현지화 시스템 로직 추가

This commit is contained in:
NTG_Lenovo 2025-07-17 19:11:00 +09:00
parent ebfc5677cd
commit 8ee7d89b0c
6 changed files with 268 additions and 26 deletions

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace DDD
{
[Serializable]
public class SheetTableData
{
public string Key;
public Dictionary<string, string> LocaleValues = new(); // ex: "en" → "Potion"
}
[Serializable]
public class SheetUploadPayload
{
public Dictionary<string, List<SheetTableData>> Tables = new(); // TableName → Entries
}
[Serializable]
public class SheetDownloadPayload
{
public Dictionary<string, List<Dictionary<string, string>>> Tables = new(); // TableName → Rows (Key, en, ko, ja ...)
}
}

View File

@ -0,0 +1,48 @@
using UnityEngine;
using UnityEngine.Networking;
using System.Text;
using System.Threading.Tasks;
namespace DDD
{
public static class GoogleSheetWebClient
{
public static async Task<string> Get(string url)
{
var req = UnityWebRequest.Get(url);
var op = req.SendWebRequest();
while (!op.isDone)
await Task.Yield();
if (req.result != UnityWebRequest.Result.Success)
{
Debug.LogError("GET Failed: " + req.error);
return null;
}
return req.downloadHandler.text;
}
public static async Task<string> Post(string url, string json)
{
var req = new UnityWebRequest(url, "POST");
byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
req.uploadHandler = new UploadHandlerRaw(bodyRaw);
req.downloadHandler = new DownloadHandlerBuffer();
req.SetRequestHeader("Content-Type", "application/json");
var op = req.SendWebRequest();
while (!op.isDone)
await Task.Yield();
if (req.result != UnityWebRequest.Result.Success)
{
Debug.LogError("POST Failed: " + req.error);
return null;
}
return req.downloadHandler.text;
}
}
}

View File

@ -0,0 +1,66 @@
#if UNITY_EDITOR
using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEditor.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
namespace DDD
{
public static class LocalizationExporter
{
public static async void ExportAllToSheet(string webAppUrl)
{
var collections = LocalizationEditorSettings.GetStringTableCollections();
var exportPayload = new SheetUploadPayload();
List<string> localeOrder = GetOrderedLocaleCodes();
foreach (var collection in collections)
{
string tableName = collection.TableCollectionName;
var shared = collection.SharedData;
var entries = new List<SheetTableData>();
foreach (var sharedEntry in shared.Entries)
{
var row = new SheetTableData { Key = sharedEntry.Key };
foreach (var localeCode in localeOrder)
{
var table = collection.GetTable(localeCode) as StringTable;
if (table != null)
{
string value = table.GetEntry(sharedEntry.Id)?.Value ?? "";
row.LocaleValues[localeCode] = value;
}
}
entries.Add(row);
}
exportPayload.Tables[tableName] = entries;
}
string json = JsonConvert.SerializeObject(exportPayload);
Debug.Log($"Localization Exporting...");
var response = await GoogleSheetWebClient.Post(webAppUrl, json);
Debug.Log($"<color=green>[Localization Export 완료]</color> 응답: {response}");
}
/// <summary>
/// Localization Settings에 등록된 Locale 순서대로 Locale 코드 리스트 반환
/// </summary>
public static List<string> GetOrderedLocaleCodes()
{
var locales = LocalizationSettings.AvailableLocales.Locales;
var result = new List<string>();
foreach (var locale in locales)
{
result.Add(locale.Identifier.Code); // 예: "ko", "en", "ja"
}
return result;
}
}
}
#endif

View File

@ -0,0 +1,56 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using UnityEngine.Localization.Tables;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEditor.Localization;
namespace DDD
{
public static class LocalizationImporter
{
public static async void ImportAllFromSheet(string webAppUrl)
{
string json = await GoogleSheetWebClient.Get(webAppUrl);
if (string.IsNullOrEmpty(json)) return;
var payload = JsonConvert.DeserializeObject<SheetDownloadPayload>(json);
foreach (var kv in payload.Tables)
{
string tableName = kv.Key;
List<Dictionary<string, string>> rows = kv.Value;
var collection = LocalizationEditorSettings.GetStringTableCollection(tableName);
if (collection == null)
{
Debug.LogWarning($"[Localization] Table not found: {tableName}");
continue;
}
var shared = collection.SharedData;
foreach (var row in rows)
{
if (!row.TryGetValue("Key", out var key)) continue;
var sharedEntry = shared.GetEntry(key) ?? shared.AddKey(key);
foreach (var localeCode in row.Keys)
{
if (localeCode == "Key") continue;
var table = collection.GetTable(localeCode) as StringTable;
if (table == null) continue;
table.AddEntry(sharedEntry.Id, row[localeCode]);
EditorUtility.SetDirty(table);
}
}
AssetDatabase.SaveAssets();
}
Debug.Log("<color=green>[Localization Import]</color> 완료");
}
}
}
#endif

View File

@ -1,31 +1,56 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using UnityEngine.Localization.Settings;
using System.Linq;
namespace DDD
{
public class LocalizationManager : MonoBehaviour
public enum TableName
{
[SerializeField]
private string _webUrl = "https://script.google.com/macros/s/AKfycbx6ZrQNJIot1A_uwjilgOxHEm7zPommHyi7nH-x1d8sNgMEUeoqHf8iwvEnA1AxKBU6/exec";
// [MenuItem("Tools/Localization/Import All From Sheet")]
// public static void ImportAll()
// {
// var url = GetManager()?.WebUrl;
// if (string.IsNullOrEmpty(url)) return;
//
// LocalizationImporter.ImportAll(url);
// }
//
// [MenuItem("Tools/Localization/Export All To Sheet")]
// public static void ExportAll()
// {
// var url = GetManager()?.WebUrl;
// if (string.IsNullOrEmpty(url)) return;
//
// LocalizationExporter.ExportAll(url);
// }
None = 0,
Item_Name,
Item_Description,
}
}
#endif
public static class LocalizationManager
{
/// <summary>
/// 현재 선택된 로케일 기준으로 로컬라이징 텍스트를 가져옵니다.
/// </summary>
public static string GetString(TableName table, string key)
{
if (table == TableName.None || string.IsNullOrEmpty(key))
return $"[Invalid:{table}/{key}]";
var locale = LocalizationSettings.SelectedLocale;
var tableName = table.ToString();
var stringTable = LocalizationSettings.StringDatabase.GetTable(tableName, locale);
if (stringTable == null)
return $"[Missing Table:{tableName}]";
var entry = stringTable.GetEntry(key);
if (entry == null)
return $"[Missing Key:{key}]";
return entry.GetLocalizedString();
}
/// <summary>
/// 현재 사용 중인 로케일 코드 반환 (예: "ko", "en", "ja")
/// </summary>
public static string GetCurrentLocaleCode()
{
return LocalizationSettings.SelectedLocale.Identifier.Code;
}
/// <summary>
/// 로케일 코드로 현재 언어를 설정합니다. (예: "ko", "en", "ja")
/// </summary>
public static void SetLocale(string code)
{
var locale = LocalizationSettings.AvailableLocales.Locales
.FirstOrDefault(l => l.Identifier.Code == code);
if (locale != null)
LocalizationSettings.SelectedLocale = locale;
}
}
}

View File

@ -0,0 +1,23 @@
#if UNITY_EDITOR
using UnityEditor;
namespace DDD
{
public static class LocalizationSyncTool
{
public static readonly string WebAppUrl = "https://script.google.com/macros/s/AKfycbwVQ7_x0Didf_13h3qPB9lSMobBR9xr6nLffj_n8znNvfs-pdNylNA7nWzd2R-_IHGf/exec";
[MenuItem("Tools/Localization/Google Sheet → Unity")]
public static void ImportAll()
{
LocalizationImporter.ImportAllFromSheet(WebAppUrl);
}
[MenuItem("Tools/Localization/Unity → Google Sheet")]
public static void ExportAll()
{
LocalizationExporter.ExportAllToSheet(WebAppUrl);
}
}
}
#endif