概要
UnrealEngineでのStringTableについてのメモ書きと、コマンドレットを使ってcsvファイルからのインポートとcsvファイルへのエクスポートコード例です。
環境
Windows10
Visual Studio 2017
UnrealEngine 4.25
参考
以下を参考にさせて頂きました、ありがとうございます。
UE4公式 : UCommandlet
UE4公式 : Commandlets
UE4公式 : 文字列テーブル
[UE4] String Tableの紹介
関連ソース
"Engine\Source\Runtime\Engine\Classes\Commandlets\Commandlet.h"
ストリングテーブルについて
ローカライズ用アセットとして使うことができる文字列テーブルです。Key
とSourceString
が設定でき、Key
に紐づいたSourceString
を表示することによってアセット切り替え(言語切り替え)を行っても表示側の処理を変えずに表示文字列を切り替えることができます。
データの追加はストリングテーブルエディタの下部にて追加もできますが、CSVファイルでのインポートなどもできます。
BPノード例
GetStringTableEntrySourceString
GetStringTableEntrySourceString
はストリングテーブルに登録されている文字列を取得できます。Table Id
にストリングテーブルのアセットのパス Key
にキーを指定します。
IsStringTableEntryRegistered
IsStringTableEntryRegistered
はストリングテーブルに指定のキーが登録されているかを調べるノードです。Table Id
にストリングテーブルのアセットのパス Key
にキーを指定します。
C++コード例
上記BPをC++で書くと以下の様になります。
ストリングテーブルアセットは別途どこかでロードする必要があります。
#include "Kismet/KismetStringTableLibrary.h"
FString _String = UKismetStringTableLibrary::GetTableEntrySourceString(FName("/Game/StringTable/ST_Test.ST_Test"), FString(TEXT("StringKey01")) );
bool _IsRegist = UKismetStringTableLibrary::IsRegisteredTableEntry(FName("/Game/StringTable/ST_Test.ST_Test"), FString(TEXT("StringKey99")) );
関連エンジンソース
"Engine\Source\Runtime\Engine\Classes\Kismet\KismetStringTableLibrary.h"
コマンドレットでの操作
コマンドレットでインポート/エクスポートが可能です。
インポート
Test.csv
というCSVファイルから ストリングテーブル ST_Test
へインポートする処理です。
// アセットデータ
FAssetData _AssetData = AssetRegistry.GetAssetByObjectPath(TEXT("/Game/StringTable/ST_Test.ST_Test"));
// ストリングテーブル
UStringTable* _StringTable = Cast<UStringTable>(_AssetData.GetAsset());
// インポート元のcsv
FString _OutFiles = FString(TEXT("../../../app/Content/Localization/Test.csv"));
_StringTable->Modify();
bool _Ret = _StringTable->GetMutableStringTable()->ImportStrings(_OutFiles);
エクスポート
ストリングテーブルST_Test
からCSVファイルTest.csv
へエクスポートする処理です。
// アセットデータ
FAssetData _AssetData = AssetRegistry.GetAssetByObjectPath(TEXT("/Game/StringTable/ST_Test.ST_Test"));
// ストリングテーブル
UStringTable* _StringTable = Cast<UStringTable>(_AssetData.GetAsset());
// エクスポート先のcsv
FString _OutFiles = FString(TEXT("../../../app/Content/Localization/Test.csv"));
_StringTable->GetStringTable()->ExportStrings(_OutFiles);
クラス例
コマンドレットクラスは以下の様になります。
コード例では入出力ファイルが直値になっているので実際に使用する際はコマンドラインのオプション等で指定できると良いかと思います。(変換が面倒ですが)
#pragma once
#include "CoreMinimal.h"
#include "Commandlets/Commandlet.h"
#include "StringTableProcCommandlet.generated.h"
class UStringTable;
// ストリングテーブル処理コマンドレットクラス
UCLASS()
class UStringTableProcCommandlet : public UCommandlet
{
GENERATED_BODY()
public:
UStringTableProcCommandlet(const FObjectInitializer& ObjectInitializer);
virtual int32 Main(const FString& CmdLineParams) override;
};
#include "StringTableProcCommandlet.h"
#include "AssetRegistry/Public/AssetData.h"
#include "AssetRegistry/Public/AssetRegistryModule.h"
#include "AssetRegistry/Public/AssetRegistryHelpers.h"
#include "CoreUObject/Public/UObject/ConstructorHelpers.h"
#include "Internationalization/StringTable.h"
#include "Internationalization/StringTableCore.h"
#include "Internationalization/StringTableCoreFwd.h"
DEFINE_LOG_CATEGORY_STATIC(LogTextSTProcCommandlet, Log, All);
UStringTableProcCommandlet::UStringTableProcCommandlet(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
LogToConsole = true;
}
int32 UStringTableProcCommandlet::Main(const FString& CmdLineParams)
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
TArray<UPackage*> _PackagesToSave;
bool _IsImport = false;
bool _IsExport = false;
// CSVファイルパス
const TArray<const TCHAR*> _ImportCsvFiles = {
TEXT("../../../app/Content/Localization/ST_Test1.csv"),
};
const TArray<const TCHAR*> _ExportCsvFiles = {
TEXT("../../../app/Content/Localization/ST_Test2.csv"),
};
// アセットデータ
FAssetData _AssetData = AssetRegistry.GetAssetByObjectPath(TEXT("/Game/StringTable/ST_Test.ST_Test"));
// ストリングテーブル
UStringTable* _StringTable = Cast<UStringTable>(_AssetData.GetAsset());
// アセットデータチェック
if (!_AssetData.IsValid() || _StringTable == nullptr) {
UE_LOG(LogTextSTProcCommandlet, Display, TEXT("File Not Found."));
return(1);
}
TArray<FString> Tokens;
TArray<FString> Switches;
ParseCommandLine(*CmdLineParams, Tokens, Switches);
// オプションチェック
for(const auto& _It : Switches){
if( _It.Equals(TEXT("import"), ESearchCase::CaseSensitive)){
_IsImport = true;
}else
if( _It.Equals(TEXT("export"), ESearchCase::CaseSensitive)){
_IsExport = true;
}
}
if( !_IsImport && !_IsExport){
UE_LOG(LogTextSTProcCommandlet, Display, TEXT("NotFound SwitchOption(-Import or -Export)"));
return(0);
}
//---------------------
// インポート処理
if(_IsImport){
_StringTable->Modify();
bool _Ret = _StringTable->GetMutableStringTable()->ImportStrings(_ImportCsvFiles[0]);
_PackagesToSave.Add(_AssetData.GetPackage());
}
// アセットセーブ
for (const auto& _It : _PackagesToSave) {
// 保存ファイル名
const auto _FileName = FString::Printf(TEXT("../../../app/Content/StringTable/ST_Test.uasset"));
// パッケージ保存
UPackage::SavePackage(_It, nullptr, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *_FileName);
}
//---------------------
// エクスポート処理
if(_IsExport){
_StringTable->GetStringTable()->ExportStrings(_ExportCsvFiles[0]);
}
return(0);
}
実行コマンドは以下の様になります(引数で分岐しているだけですのでエクスポートもほぼ一緒です)。
オプションでファイル名等を指定できるようにすればより扱いやすくなるかと思います。
# インポート
> {エンジンパス}\Binaries\Win64\UE4Editor-Cmd.exe {プロジェクトパス}\MyProject.uproject -run=StringTableProc -import
まとめ
ローカライズ文字列をストリングテーブルを使って管理する際に、コマンドレットでのインポートを使うと捗ると思います。特にローカライゼーションダッシュボードを使ったローカライズ処理ではストリングテーブル使用が必須の様です。