天天看點

UE4 從無到有純 C++ & Slate 開發沙盒遊戲(六) 語言切換功能的實作

實作遊戲的中英文對應

由于界面标題中有中文亂碼,這個可以通過修改編譯器的編碼為UTF-8解決,也可以通過UE4自帶的本地化方法解決,自帶方法包括:

1. TEXT() 建立一個通用的 String 類型,  TEXT("Hello");

2. LOCTEXT() 建立一個本地化文字,  LOCTEXT ("ID" "String");

3. NSLOCTEXT() 在一個域名空間内的本地化,  NSLOCTEXT (Namespace"," "Name","Hello"); 

以下為使用2、3兩種方法來實作的本地化

建立一個類 SlAiInternation

UE4 從無到有純 C++ & Slate 開發沙盒遊戲(六) 語言切換功能的實作

隻需要頭檔案就好,将項目下的.cpp檔案移除,資源檔案夾中的檔案删除

UE4 從無到有純 C++ & Slate 開發沙盒遊戲(六) 語言切換功能的實作

編輯檔案

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Public\Date\SlAiInternation.h

#include "CoreMinimal.h"

class SLAICOURSE_API SlAiInternation
{
public:

    static void Register(FText, Value)
        [
            return;
        ]
};

#define LOCTEXT_NAMESPACE "SlAiMenu"

/**
*主菜單
*/
SlAiInternation::Register(LOCTEXT("Menu", "Menu"));
SlAiInternation::Register(LOCTEXT("startGame", "startGame"));                  //開始遊戲
SlAiInternation::Register(LOCTEXT("Gameoption", "Gameoption"));                //遊戲設定
SlAiInternation::Register(LOCTEXT("QuitGame", "QuitGame"));                    //退出遊戲
SlAiInternation::Register(LOCTEXT("NewGame", "NewGame"));                      //新遊戲
SlAiInternation::Register(LOCTEXT("LoadRecord", "LoadRecord"));                //加載存檔
SlAiInternation::Register(LOCTEXT("ChooseRecord", "ChooseRecord"));            //選擇存檔

/**
*進入遊戲界面
*/
SlAiInternation::Register(LOCTEXT("RecordName", "RecordName"));                         //存檔名
SlAiInternation::Register(LOCTEXT("EnterGame", "EnterGame"));                           //進入遊戲
SlAiInternation::Register(LOCTEXT("EnterRecord", "EnterRecord"));                       //進入存檔
SlAiInternation::Register(LOCTEXT("RecordNameHint", "Input Record Name!"));             //輸入存檔名
SlAiInternation::Register(LOCTEXT("NameRepeatedHint", "Record Name Repeated!"));        //輸入存檔名

/**
*遊戲設定界面
*/
SlAiInternation::Register(LOCTEXT("Chinese", "Chinese"));                //中文
SlAiInternation::Register(LOCTEXT("English", "English"));                //英文
SlAiInternation::Register(LOCTEXT("Music", "Music"));                    //音樂
SlAiInternation::Register(LOCTEXT("Sound", "Sound"));                    //音效

/**
*公用
*/
SlAiInternation::Register(LOCTEXT("GoBack", "GoBack"));                 //傳回
#undef LOCTEXT_NAMESPACE

/************************************************************************************************
*        SlAiInternation::Register(NSLOCTEXT("SlAiMenu", "Menu", "Menu"))
* 
*上方三行代碼與這一行代碼作用是一樣的,差別在于上方三行是将域名放到外面,而NSLOCTEXT是将域名放到裡面
* 其他檔案中想要調用該本地化文字的時候,可以直接通過 NSLOCTEXT 調用,不用很麻煩的先去聲明域名再去調用 LOCTEXT
*************************************************************************************************/      

NSLOCTEXT 的調用方式

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\UI\Widget\SSlAiMenuWidget.cpp

#include "UI/Widget/SSlAiMenuWidget.h"
#include "SlateOptMacros.h"
#include "UI/Style/SlAiStyle.h"
#include "UI/Style/SlAiMenuWidgetStyle.h"
#include "Widgets/Layout/SBox.h" 
#include "Widgets/Images/SImage.h"
#include "Widgets/Text/STextBlock.h"

BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SSlAiMenuWidget::Construct(const FArguments& InArgs)
{

    MenuStyle = &SlAiStyle::Get().GetWidgetStyle<FSlAiMenuStyle>("BPSlAiMenuStyle");
    
    ChildSlot
    [

        SAssignNew(RootSizeBox, SBox)
        [
            SNew(SOverlay)

            +SOverlay::Slot()
                .HAlign(HAlign_Fill)
                .VAlign(VAlign_Fill)
                .Padding(FMargin(0.f, 50.f, 0.f, 0.f)) 
                [
                    SNew(SImage)
                    .Image(&MenuStyle->MenuBackgroundBrush)
                ]

            +SOverlay::Slot()
                .HAlign(HAlign_Left)
                .VAlign(VAlign_Center)
                .Padding(FMargin(0.f, 25.f, 0.f, 0.f))
                [
                    SNew(SImage).Image(&MenuStyle->LeftIconBrush)
                ]

            + SOverlay::Slot()
                .HAlign(HAlign_Right)
                .VAlign(VAlign_Center)
                .Padding(FMargin(0.f, 25.f, 0.f, 0.f))
                [
                    SNew(SImage).Image(&MenuStyle->RightIconBrush)
                ]

            + SOverlay::Slot()
                .HAlign(HAlign_Center)
                .VAlign(VAlign_Top)
                [
                    SNew(SBox)
                    .WidthOverride(400.f)
                    .HeightOverride(100.f)
                    [
                        SNew(SBorder)
                        .BorderImage(&MenuStyle->TitleBorderBrush)
                        .HAlign(HAlign_Center)
                        .VAlign(VAlign_Center)
                        [
                            SAssignNew(TitleText, STextBlock)
                            .Font(SlAiStyle::Get().GetFontStyle("MenuItemFort")
                            .Text(NSLOCTEXT("SlAiMenu", "Menu", "Menu"))          //使用 NSLOCTEXT 宏插入的本地化文字,三個參數為:域名 Key Value
                        ]
                    ]
                ]
        ]
    ];

    RootSizeBox->SetWidthOverride(600.f);
    RootSizeBox->SetHeightOverride(510.f);

}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION      

在UE4中的菜單,Window ->  Localization Dashboard

打開本地化設定

我的 Source 檔案下包含了所有的頭檔案,UE4會從該目錄下搜尋所有有關于 LOCTEXT 以及 NSLOCTEXT 兩個宏的本地化文字

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

Add New Culture 新增中文,并點選 English 前方圓鈕将英文設定為預設選項

點選Gather Text尋找本地化文字,下圖為尋找結果,找到21個英文語言,有1個中文翻譯(這一個是我之前加的,如果從未添加過這裡應該是0)

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

 點選添加中文翻譯

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

 寫入對應的中文,然後儲存

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

 點選 Count Words 重新整理進度

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作
UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

然後再點選 Compile Text 進行編譯,讓UE4将這個檔案拷貝到 Cultures 本地化檔案夾的格式檔案中

它會在本地生成兩個檔案夾 en ch 這裡放置翻譯的一些内容

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

這時候在運作遊戲,便不會再顯示中文亂碼

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

代碼控制UI界面的文字顯示:

#include "Internationalization/Internationalization.h"                        //一個關于本地化的頭檔案
/**
 *切換語言
 */
 FInternationalization::Get().SetCurrentCulture(TEXT("en"));
 //FInternationalization::Get().SetCurrentCulture(TEXT("ch"));
      

遊戲中實作中英文切換

接下來寫兩個類,來标記遊戲中目前是中文還是英文

SlAiTypes 存放基礎的資料結構

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

SlAiDataDandle 來實作切換中英文的方法

UE4 從無到有純 C++ &amp; Slate 開發沙盒遊戲(六) 語言切換功能的實作

SlAiTypes 也不要 .cpp 檔案,留一個 .h 檔案便可,将其删除,并移出項目

d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Public\Data\SlAiTypes.h

#include "CoreMinimal.h"

UENUM()
enum class ECultrueTeam : uint8
{
    EN = 0,
    ZH
};      

d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Public\Data\SlAiDataHandle.h

#include "SlAiTypes.h"
#include "CoreMinimal.h"


class SLAICOURSE_API SlAiDataHandle
{
public:
    SlAiDataHandle();

    static void Initialize();

    static TSharedPtr<SlAiDataHandle> Get();

    //修改中英文
    void ChangeLocalizationCultrue(ECultrueTeam Culture);

public:
    /**
    * 目前語言狀态,儲存後轉換場景後還會用到
    * 這裡沒有使用UE4 GamePlay 架構的 GameInstance,變量直接寫到C++類中除非你主動銷毀,否則他會一直存在
    */
    ECultrueTeam CurrentCulture;

private:
    //建立單例
    static TSharedRef<SlAiDataHandle> Create();

private:
    static TSharedPtr<SlAiDataHandle> DataInstance;

};      

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\Data\SlAiDataHandle.cpp

#include "Data/SlAiDataHandle.h"


TSharedPtr<SlAiDataHandle> SlAiDataHandle::DataInstance = NULL;

void SlAiDataHandle::Initialize()
{
    if (!DataInstance.IsValid())
    {
        DataInstance = Create();
    }
}

TSharedPtr<SlAiDataHandle> SlAiDataHandle::Get()
{
    Initialize();
    return DataInstance;
}

TSharedRef<SlAiDataHandle> SlAiDataHandle::Create()
{
    /**
    *MakeShareable 可以用來建立共享指針和共享引用
    */
    TSharedRef<SlAiDataHandle> DataRef = MakeShareable(new SlAiDataHandle());
  return DataRef;
}

SlAiDataHandle::SlAiDataHandle()
{

}

void SlAiDataHandle::ChangeLocalizationCultrue(ECultrueTeam Culture)
{
    switch (Culture)
    {
    case ECultrueTeam::EN:
        FInternationalization::Get().SetCurrentCulture(TEXT("en"));
        break;
    case ECultrueTeam::ZH:
        FInternationalization::Get().SetCurrentCulture(TEXT("zh"));
        break;
    }
    //指派
    CurrentCulture = Culture;
}