はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】LocalizationのStringTableCollectionを一括でCSVに出力するエディタ拡張を作った

はじめに

Localizationで利用している大量のStringTableCollectionCSVに出力してほしいとの要望があったのですが、一々LocalizationTablesWindowをいじってCSVに出力するのはかなり辛そうだと思いました。

LocalizationTablesWindow

ぱっと調べてみたところUnityEditor.Localization.Plugins.CSV.Csvというクラスがpublicで公開されていたので、これを弄れば自動化できそうだと思いやってみたら結構簡単にいけました。
docs.unity3d.com

こちらを今回は紹介したいと思います。

使い方

こちらのコードをEditorフォルダ(or自分でasmdefを作る)に入れれば導入は終わりです。
github.com

メニューバーよりTools -> StringTableCollectionCsvExporterを選択してウィンドウを開きます。

StringTableCollectionCsvExporter

Select Output Folderボタンを押して出力先のフォルダを選択、Export Csvボタンを押せばcsvが出力されます。

コード

using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEditor;
using UnityEditor.Localization;
using UnityEditor.Localization.Plugins.CSV;

public class StringTableCollectionCsvExporterWindow : EditorWindow
{
    private const string StringTableCollectionFilter = "t:StringTableCollection";
    private string _outputPath;

    [MenuItem("Tools/StringTableCollectionCsvExporter")]
    private static void Init()
    {
        var instance = GetWindow<StringTableCollectionCsvExporterWindow>();
        instance._outputPath = Application.dataPath;
        instance.minSize = new Vector2(700, 80);
    }

    private void OnGUI()
    {
        EditorGUILayout.LabelField("OutputFolder", _outputPath);
        if (GUILayout.Button("Select Output Folder"))
        {
            var selectedPathName = EditorUtility.OpenFolderPanel( "Select Output Folder",  "",  "");
            if (!string.IsNullOrEmpty(selectedPathName)) _outputPath = selectedPathName;
        }

        if (GUILayout.Button("Export Csv"))
        {
            var guids = AssetDatabase.FindAssets(StringTableCollectionFilter);
            var assetPaths = guids.Select(AssetDatabase.GUIDToAssetPath);
            var stringTableCollections = assetPaths.Select(AssetDatabase.LoadAssetAtPath<StringTableCollection>);

            foreach (var stringTableCollection in stringTableCollections)
            {
                using var textWriter = new StreamWriter($"{_outputPath}/{stringTableCollection.name}.csv", false, Encoding.UTF8);
                Csv.Export(textWriter, stringTableCollection);
            }

            AssetDatabase.Refresh();
        }
    }
}

github.com

補足

後から調べてわかったのですが、公式ドキュメントのサンプルにも同じことをしているものがありました。

[MenuItem("Localization/CSV/Export All CSV Files(With Extensions)")]
public static void PullAllExtensions()
{
    // Get every String Table Collection
    var stringTableCollections = LocalizationEditorSettings.GetStringTableCollections();

    foreach (var collection in stringTableCollections)
    {
        // Its possible a String Table Collection may have more than one extension.
        foreach (var extension in collection.Extensions)
        {
            if (extension is CsvExtension csvExtension)
            {
                if (!string.IsNullOrEmpty(csvExtension.File))
                {
                    using (var stream = new StreamWriter(csvExtension.File, false, Encoding.UTF8))
                    {
                        Csv.Export(stream, collection, csvExtension.Columns);
                    }
                }
            }
        }
    }
}

Class Csv | Localization | 1.0.5

またImportも用意されていますね。

[MenuItem("Localization/CSV/Import All CSV Files")]
public static void ImportAllExtensions()
{
    // Get every String Table Collection
    var stringTableCollections = LocalizationEditorSettings.GetStringTableCollections();

    foreach (var collection in stringTableCollections)
    {
        // Its possible a String Table Collection may have more than one extension.
        foreach (var extension in collection.Extensions)
        {
            if (extension is CsvExtension csvExtension)
            {
                if (!string.IsNullOrEmpty(csvExtension.File) && File.Exists(csvExtension.File))
                {
                    using (var stream = new StreamReader(csvExtension.File))
                    {
                        Csv.ImportInto(stream, collection, csvExtension.Columns);
                    }
                }
            }
        }
    }
}

ちょっと悲しいです。