最近研究了一下本地化,給大家用簡單易懂的方式說明我是怎么實現的,使用CSV表格填寫翻譯,然后在Godot中讀取為字典
表格填寫
首先,我們表格可以按照下面這種格式填寫
id | zh | en | ja | ru | es | de | fr |
apple | 蘋果 | apple | リンゴ | яблоко | manzana | Apfel | pomme |
banana | 香蕉 | banana | バナナ | банан | plátano | Banane | banane |
orange | 橙子 | orange | オレンジ | апельсин | naranja | Orange | orange |
大家看表格應該能明白,用第一列作為鍵,然后再用語言作為第二層的鍵,就能調用到對應語言的文本了,有一點需要注意,我們保存的時候,格式需要選擇為 CSV UTF-8(用逗號分隔)的格式
打開查看,我們可以看到是下面這種格式
有一點需要注意,當我們打開表格的時候是有保護的,這時候不能在這里面修改保存,關閉表格即可
導入表格
我們直接把表格拖入到Godot里面,你可能會注意到Godot報錯
Failed to open 'C:\Users\Administrator\Videos\Fruits.csv'.
我們在資源管理器進行移動,Godot中會自動創建一堆.translation格式的翻譯文件
我們需要在導入中設置為原樣導出,選擇后點擊重新導入即可
接下來,你會發現文件變成了X號的圖標,不要雙擊打開他,Godot會直接閃退,我們刪除這些創建出來的.translation文件就行
讀取代碼
首先,我們需要創建一個雙層字典用來保存翻譯文本
using Godot.Collections; //注意,使用字典就需要寫這個[Export] //暴露在編輯器中
public Dictionary<string, Dictionary<string, string>> language = new Dictionary<string, Dictionary<string, string>>();private string csv_language_path = "res://Language/Fruits.csv"; //文件路徑
public string Now_Language = "zh"; //當前語言
然后我們寫一個函數,在初始化的時候把數據寫入字典
void Load_CSV_Language(){if (!FileAccess.FileExists(csv_language_path)) //判斷文件是否存在{GD.Print($"{csv_language_path}文件不存在");return;}var file = FileAccess.Open(csv_language_path, FileAccess.ModeFlags.Read);var header = file.GetLine().Split(","); //獲取語言頭while (!file.EofReached()) //循環,直到指向尾部{Dictionary<string, string> lang = new Dictionary<string, string>(); //創建內層字典var line = file.GetLine().Split(","); //獲取行(鍵,語言,語言,語言)if (string.IsNullOrWhiteSpace(line[0])) continue; //跳過空行,防止越界for (int i = 1; i < line.Length; i++){lang.Add(header[i], line[i]);}language.Add(line[0], lang);}file.Close(); //關閉文件流}
接下來,我們寫一個獲取對應文本的函數方法即可
public string Get_Language(string key) //返回本地化語言{return language[key][Now_Language];}
單例加載
有一點,在C#中使用Godot的自動加載功能,我們需要額外寫一些代碼
我這里則是放在了樹的加載函數中,大家根據需要進行調整
public static LanguageManager Instance;public override void _EnterTree(){Instance = this;Load_CSV_Language(); //調用加載字典函數}public override void _ExitTree(){Instance = null;}
這樣,我們運行場景,就能看到場景的根節點下,多了一個節點
接下來,我們只需要在其他節點中獲取即可調用?Get_Language?方法了
public LanguageManager languageManager;public override void _Ready(){languageManager = GetTree().Root.GetNode<LanguageManager>("LanguageManager");}
切換語言
為了在切換語言的時候更改場景的文本,我們先把所有的設置文本的函數都放在一個函數中,大家可以參照我的示例進行修改
public void SetLanguage(){Get_Language();SetText();}public void Get_Language() //獲取翻譯{name = languageManager.Get_Language($"{id}");}private void SetText() //設置文本{T_name.Text = name;}
我們修改本地化腳本的?Now_Language?變量
private string _Now_Language = "zh";public string Now_Language{get => _Now_Language;set{_Now_Language = value;UpdateLanguage(); //修改值時調用}}
我們可以給腳本的節點加上分組,使用CallGroup方法調用函數
public void UpdateLanguage() //切換語言{GetTree().CallGroup("Text", "SetLanguage"); //通知組,調用設置語言方法}
這里我創建的組叫“Text”,我們需要在Godot中把組分給節點(或者在腳本中使用AddToGroup方法也可以)
這樣,我們修改?Now_Language?變量,文本就會發生改變
結語
通過這種結構化的雙層字典方案,我們成功構建了一個動態可擴展的本地化系統。如果項目文本量巨大,我們可以進行異步加載來進行優化,大家可以根據自己的需要進行修改。