[Godot] C#读取CSV表格创建双层字典实现本地化

发布于:2025-06-14 ⋅ 阅读:(29) ⋅ 点赞:(0)

最近研究了一下本地化,给大家用简单易懂的方式说明我是怎么实现的,使用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文件就行

读取代码

首先,我们需要创建一个双层字典用来保存翻译文本

[Export]    //暴露在编辑器中
public Godot.Collections.Dictionary<string, Godot.Collections.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 变量,文本就会发生改变

结语

通过这种结构化的双层字典方案,我们成功构建了一个动态可扩展的本地化系统。如果项目文本量巨大,我们可以进行异步加载来进行优化,大家可以根据自己的需要进行修改。


网站公告

今日签到

点亮在社区的每一天
去签到