https://github.com/kastro723/LocalizationEditor

 

GitHub - kastro723/LocalizationEditor

Contribute to kastro723/LocalizationEditor development by creating an account on GitHub.

github.com

테스트 실행 이미지
엑셀 테스트 데이터

+++

 

using UnityEngine;
using UnityEngine.UI;

public class TestLocalization : MonoBehaviour
{
    [SerializeField] private Button[] changeLanBtns;

    [SerializeField] private Button getValue;

    void Start()
    {

        string Test1 = LocalizationManager.instance.GetLocalString(LocalizationConstants.TROPHY_POPUP_TITLE_FOR_UNLOCK);

        Debug.Log(Test1);


        changeLanBtns[0].onClick.AddListener(() => LocalizationManager.instance.SetLanguage("kr"));
        changeLanBtns[1].onClick.AddListener(() => LocalizationManager.instance.SetLanguage("en"));
        changeLanBtns[2].onClick.AddListener(() => LocalizationManager.instance.SetLanguage("jp"));

        getValue.onClick.AddListener(() =>
        {
            string value = LocalizationManager.instance.GetLocalString(LocalizationConstants.TROPHY_POPUP_TITLE_FOR_UNLOCK);
            Debug.Log(value);
        });
    }
}

테스트 해본 스크립트

 

public interface ILocalization
{
    string GetLocalString(string key);
}

ILocalization.cs

 

using System.Collections.Generic;
using UnityEngine;
using System.IO;
using ExcelDataReader;
using System.Data;


public class LocalizationManager : ILocalization
{
    public static readonly LocalizationManager instance = new LocalizationManager();

    private string language;
    private Dictionary<string, string> dicLocalizationData;

    private LocalizationManager()
    {
        dicLocalizationData = new Dictionary<string, string>();
        Init();
    }

    public void Init() // 초기 설정
    {
        // 기기의 기본 언어 설정을 가져옴
        SystemLanguage systemLanguage = Application.systemLanguage;
        string defaultLanguage = ConvertSystemLanguageToCode(systemLanguage); // 기기의 시스템 언어를 언어 코드로 변환

        language = PlayerPrefsManager.Instance.GetString("Language", defaultLanguage); // 사용자가 설정한 언어가 없다면 기기의 기본 언어를 사용
        PlayerPrefsManager.Instance.SetString("Language", language); // 현재 언어 설정을 저장

        Debug.Log("current language: " + language);

        LoadLocalizationData();
    }


    private string ConvertSystemLanguageToCode(SystemLanguage language)
    {
        switch (language)
        {
            case SystemLanguage.Korean:
                return "kr";
            case SystemLanguage.English:
                return "en";
            case SystemLanguage.Japanese:
                return "jp";
            default:
                return "kr"; // 기본값으로 한국어 설정
        }
    }

    private void LoadLocalizationData()
    {
        string filePath = LocalizationConstants.excelFilePath; // LocalizationConstants.cs에서 정의된 경로를 사용

        using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
        {
            using (var reader = ExcelReaderFactory.CreateReader(stream))
            {
                var result = reader.AsDataSet();
                DataTable table = result.Tables[0];

                // 언어 코드는 1행 2열 부터 위치함.
                var languageCodes = new List<string>();
                for (int columnIndex = 1; columnIndex < table.Columns.Count; columnIndex++)
                {
                    languageCodes.Add(table.Rows[0][columnIndex].ToString()); // 1행 2열부터 언어 코드를 읽음
                }

                // 데이터는 3행부터 시작합니다.
                for (int rowIndex = 2; rowIndex < table.Rows.Count; rowIndex++)
                {
                    var row = table.Rows[rowIndex];
                    string key = row[0].ToString(); // 첫 번째 열은 키 값입니다.

                    for (int columnIndex = 1; columnIndex < languageCodes.Count + 1; columnIndex++)
                    {
                        string languageCode = languageCodes[columnIndex - 1]; // 언어 코드 리스트에서 언어 코드를 가져옴
                        string value = row[columnIndex].ToString();
                        string dicKey = $"{key}_{languageCode}".ToUpper(); // 복합 키 생성 (예: TROPHY_POPUP_TITLE_FOR_UNLOCK_KR)

                        dicLocalizationData[dicKey] = value; // 딕셔너리에 언어별 값 저장
                    }
                }
            }
        }
    }

    public void SetLanguage(string lan) // 언어 변경
    {
        language = lan;
        language = language.ToLower(); // 대, 소문자를 소문자로 통합
        if (language == "kr" || language == "en" || language == "jp") // 언어 추가 시, 조건 추가
        {
            PlayerPrefsManager.Instance.SetString("Language", language); // 현재 언어 설정을 저장, (kr, en, jp)
            Debug.Log("current language: " + language);

            dicLocalizationData.Clear();
            LoadLocalizationData(); 
        }

        else
        {
            Debug.Log("Language Invaild Input!");
        }
       
    }

    /// <summary>
    /// 언어별로 로컬라이즈된 문자열을 반환.
    /// </summary>
    /// <param name="key">로컬라이제이션 키 (예: "TROPHY_POPUP_TITLE_FOR_UNLOCK")</param>
    /// <returns>
    /// 현재 설정된 언어에 맞는 로컬라이즈된 문자열.
    /// 설정된 언어에 해당하는 문자열이 없을 경우 "Key {key} not found" 반환.
    /// </returns>
    /// <example>
    /// // 사용법 예시:
    /// string localizedText = LocalizationManager.instance.GetLocalString("TROPHY_POPUP_TITLE_FOR_UNLOCK");
    /// Debug.Log(localizedText); // 현재 언어가 "kr"이라면 "잠금해제!"를 출력
    /// </example>

    public string GetLocalString(string key)
    {
        string dicKey = $"{key}_{language}".ToUpper();
        if (dicLocalizationData.TryGetValue(dicKey, out string value))
        {
            return value;
        }
        return $"Key {key} not found";
    }


}

LocalizationManager.cs

 

using UnityEditor;
using UnityEngine;
using System.IO;
using ExcelDataReader;
using System.Data;
using System.Text;

public class LocalizationEditor : EditorWindow
{
    private string excelFilePath = string.Empty;
    private string classFilePath = string.Empty;

    [MenuItem("Tools/LocalizationEditor")]
    public static void ShowWindow()
    {
        var window = GetWindow(typeof(LocalizationEditor));
        window.maxSize = new Vector2(495, window.maxSize.y);
        window.minSize = new Vector2(495, 300);
        window.Show();
    }

    void OnGUI()
    {
        GUILayout.Label("Ver. 1.0.0", EditorStyles.boldLabel);

        DrawLine();

        // 드래그 앤 드롭 영역 생성
        var dragArea = GUILayoutUtility.GetRect(0f, 100f, GUILayout.ExpandWidth(true));
        GUI.Box(dragArea, "Drag & Drop Excel file here or Click 'Generate Constants Class'");

        if (dragArea.Contains(Event.current.mousePosition) && Event.current.type == EventType.DragUpdated)
        {
            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
            Event.current.Use();
        }
        else if (dragArea.Contains(Event.current.mousePosition) && Event.current.type == EventType.DragPerform)
        {
            DragAndDrop.AcceptDrag();

            foreach (var dragged_object in DragAndDrop.objectReferences)
            {
                var path = AssetDatabase.GetAssetPath(dragged_object);
                if (!string.IsNullOrEmpty(path) && path.EndsWith(".xlsx"))
                {
                    excelFilePath = path;

                    // 새로운 .xlsx 파일이 선택될 때 기존 경로 초기화
                    classFilePath = "";
                    break;
                }
            }
            Event.current.Use();
        }


        if (GUILayout.Button("Generate Constants Class") && !string.IsNullOrEmpty(excelFilePath))
        {
            GenerateConstantsClass(excelFilePath);
        }

        DrawLine();

        GUILayout.BeginHorizontal();
        GUILayout.Label("Selected Excel File:    ", GUILayout.ExpandWidth(false));
        GUI.enabled = false;
        GUILayout.TextField(excelFilePath, GUILayout.ExpandWidth(true));
        GUI.enabled = true;
        GUILayout.EndHorizontal();


        GUILayout.BeginHorizontal();
        GUILayout.Label("Cs Save Path:              ", GUILayout.ExpandWidth(false));
        GUI.enabled = false;
        GUILayout.TextField(classFilePath, GUILayout.ExpandWidth(true));
        GUI.enabled = true;
        GUILayout.EndHorizontal();
    }

    private void GenerateConstantsClass(string path)
    {
        StringBuilder classBuilder = new StringBuilder();
        classBuilder.AppendLine("using System.Collections;");
        classBuilder.AppendLine("using System.Collections.Generic;");
        classBuilder.AppendLine("using UnityEngine;");
        classBuilder.AppendLine();
        classBuilder.AppendLine("public class LocalizationConstants");
        classBuilder.AppendLine("{");
        classBuilder.AppendLine();
        classBuilder.AppendLine($"    public static string excelFilePath = \"{excelFilePath}\";");
        classBuilder.AppendLine();

        using (var stream = File.Open(path, FileMode.Open, FileAccess.Read))
        {
            using (var reader = ExcelReaderFactory.CreateReader(stream))
            {
                DataTable table = reader.AsDataSet().Tables[0];
                for (int i = 2; i < table.Rows.Count; i++) // 데이터 행 시작 (3행부터)
                {
                    string key = table.Rows[i][0].ToString().ToUpper();
                    string value = table.Rows[i][0].ToString();
                    classBuilder.AppendLine($"    public const string {key} = \"{value}\";");
                }
            }
        }

        classBuilder.AppendLine("}");

        classFilePath = EditorUtility.OpenFolderPanel("Select Folder to Save Class", "Assets", "");
        if (!string.IsNullOrEmpty(classFilePath))
        {
            string targetFilePath = Path.Combine(classFilePath, "LocalizationConstants.cs");

            // 파일이 이미 존재하는지 확인
            if (File.Exists(targetFilePath))
            {
                if (EditorUtility.DisplayDialog("File Exists", "The file already exists. Do you want to overwrite it?", "Yes", "No"))
                {
                    // yes를 선택하면 덮어쓰기
                    WriteToFile(targetFilePath, classBuilder.ToString());
                    EditorUtility.DisplayDialog("Success", "Class file has been successfully overwritten.", "OK"); 
                }
                // no를 선택하면 아무것도 하지 않음
            }
            else
            {
                // 파일이 존재하지 않으면 바로 쓰기
                WriteToFile(targetFilePath, classBuilder.ToString());
                EditorUtility.DisplayDialog("Success", "Class file has been successfully generated.", "OK"); 
            }
        }
    }

    private void WriteToFile(string filePath, string content)
    {
        File.WriteAllText(filePath, content);
        AssetDatabase.Refresh();
    }
    private void DrawLine()
    {
        var rect = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(true));
        EditorGUI.DrawRect(rect, Color.gray);
    }
}

LocalizationEditor.cs

 

 

+ Recent posts