Unity游戏项目中后期如何做海外版翻译


一. 多语言和翻译的区别

1. 多语言

游戏中可以动态切换语言,比如中文、英文、西班牙文,这要求项目中要并存多语言的配置,比如i18n_zh.json、i18n_en.json、i18n_es.json,游戏根据语言设置动态加载对应的i18文件。

2. 翻译

把游戏中的中文翻译成外文,覆盖原来的中文文字,项目中只存一份i18.json

3. 优劣
方案优点缺点
多语言灵活,方便横向扩展1 逻辑上更复杂,需要在项目早期的时候就做好框架,如果后期改多语言,修改量比较大;2 如果有使用美术表现的文字,也需要支持动态切换图集,包内需要保护多种语言的美术字体
翻译代码改动少,资源简单不够灵活,不易横向扩展

二. 项目中后期如何做翻译修改

1. i18的翻译

一般项目中需要有一个i18配置,配置项目中程序用到的中文文字,结构类似如下

{
	"1": "登录成功",
	"2": "账号或密码错误",
	"3": "注册"
}

翻译的话,直接把上面的i18翻译成对应的语言文字即可,如

{
	"1": "Login successful",
	"2": "Wrong account or password",
	"3": "Regist"
}
2. excel配置表的翻译

除了i18,其他配置表中还有很多中文配置,比如背包配置表,道具名、描述等等字段都是中文的,大量的excel配置,这个时候,可以用python来批量分析这些excel配置表,把中文过滤出来
把下面的phthon脚本放在excel配置文件目录的根目录,然后执行
运行环境python2

# coding=utf-8
import xlrd
import re
import os
import io

txt_t=[]
txt = ""

def filter_zh_from_excel(f):
    xl = xlrd.open_workbook(f)
    sheets = xl.sheets()
    for sheet in sheets:
        nrows = sheet.nrows
        for i in range(nrows):
            #表头2行不检测
            if i >= 2:
                row_data = sheet.row(i)
                j = 0
                for data in row_data:
                    j = j + 1
                    if 1 == data.ctype:
                        zhmodel = re.compile(u'[\u4e00-\u9fa5]')
                        if zhmodel.search(data.value):                
                            #print('t: %s, s: %s, r: %d, c: %d, v: %s' %(f, sheet.name, i+1,j, data.value))
                            txt = '%s|%s|%d|%d|%s' %(f, sheet.name.encode('gbk'), i+1,j, data.value.encode('gbk'))
                            txt_t.append(txt.decode('gbk').encode('utf-8'))

             
def get_all_excels():
    for root, dirs, fs in os.walk('.'): 
        for f in fs:
            if f.endswith('.xlsx') or f.endswith('.xls'):
                print(os.path.join(root,  f))
                filter_zh_from_excel(os.path.join(root,  f))
                        

def write_output():
    f = open('output.csv', 'w')
    f.write('文件|sheet|行|列|内容\n ')
    for txt in txt_t:
        f.write(txt+'\n')
    f.close()


get_all_excels()
write_output()
print('done')

运行后会输出如下的表格
在这里插入图片描述
接下来,就可以把这个中文列表给外包进行翻译
当外包翻译好之后,可以得到如下的表格
在这里插入图片描述
加载到内存

Dictionary<string, string> languageMap;

修改UILabel的text的set属性

public string text
{
	set
	{	
		if(languageMap.Contains(value))
		{
			mText = languageMap[value];
		}
	}
}
3. 预设中的中文翻译

还有预设里也有中文,写个工具扫码一下

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.IO;
using System.Text;
using UnityEditor;
using System.Text.RegularExpressions;
using System;


public class PrefabLblTextZnFilter
{
    [MenuItem("Tools/扫描预设Label中文")]
    public static void StartPrefabLblTextZnFilter()
    {
        var fs = Directory.GetFiles(Application.dataPath + "\\GameRes\\", "*.prefab", SearchOption.AllDirectories);
        List<string> outputs = new List<string>();
        RunProgress(fs, "扫描预设Label中文", (f) =>
        {
            var assetPath = f.Replace(Application.dataPath, "Assets");
            var obj = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
            var lbls = obj.GetComponentsInChildren<UILabel>();
            foreach (var lbl in lbls)
            {
                if (IfContainChinse(lbl.text))
                {
                    Debug.Log(lbl.text);
                    outputs.Add(assetPath + "|" + lbl.gameObject + "|" + lbl.text);
                }
            }
        }, () =>
         {
             var outputPath = Application.dataPath + "\\..\\prefabl_lbl_zn.csv";
             using (StreamWriter sw = new StreamWriter(outputPath))
             {
                 foreach (var lin in outputs)
                 {
                     sw.WriteLine(lin);
                 }
             }
             Debug.Log("svae output done: " + outputPath);
         });
    }
    
    
    private static void RunProgress(string[] fs, string title, Action<string> itemCb, Action finishCb = null)
    {
        RunProgress<string>(fs, title, itemCb, finishCb);
    }

    private static void RunProgress<T>(T[] fs, string title, Action<T> itemCb, Action finishCb = null)
    {
        int startIndex = 0;
        Debug.Log(title + " start <<<<<");
        EditorApplication.update = delegate ()
        {
            var f = fs[startIndex];
            bool isCancel = EditorUtility.DisplayCancelableProgressBar(title, f.ToString(), (float)startIndex / fs.Length);
            try
            {
                if (null != itemCb) itemCb((T)f);
            }
            catch (Exception ex)
            {
                Debug.LogError(ex);
                isCancel = true;
            }

            startIndex++;
            if (isCancel || startIndex >= fs.Length)
            {
                EditorUtility.ClearProgressBar();
                EditorApplication.update = null;
                startIndex = 0;
                Debug.Log(title + " done >>>>>");
                if (null != finishCb)
                    finishCb();
            }
        };
    }

    private static bool IfContainChinse(string str)
    {
        return Regex.IsMatch(str, @"[\u4e00-\u9fa5]");
    }
}

点击菜单 Tools/扫描预设Label中文,输出如下的表格
在这里插入图片描述
同上给外包翻译后得到一个语言配置表,加载到内存

Dictionary<string, string> languageMap;

实例化界面预设的时候,修改UILabel的text为翻译语言

var lbls = GetComponentsInChildren<UILabel>(panelObj);
for(int i = 0, len = lbls.Lenght; i < len; ++i)
{
	var text = lbls[i].text;
	// 如果语言容器中存在
	if(languageMap.Contains(text))
	{
		lbls[i].text = languageMap[text];
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林新发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值