cocos2dx 实现国际化-简单点就是怎么用中文

当才开始接触cocos2dx的来说,要实现中文的显示,那么他们就回到网上查,当然方法也很多。这里就总结几个,然后介绍怎么封装实现国际化。

先声明一个很重要的内容:

cocos2dx 的label之类(包括所有的字符串,比如CCLog)的创建,需要传入一个const char* 即string,这里期望的是以"UTF-8"的编码形式构成的字符串。也就是运行期间他的数据时UTF-8编码的。

 

所以很多人直接在vs里面写CClog(“中文”);的时候控制台输出其实是乱码的,因为vs默认不是使用utf8编码的形式,所以不能直接用的。

但是xCode是可以的,CClog(“中文”);在xCode里面输出的就是中文。因为xcode是使用utf8编码。

所以我们要显示中文,

解决方案1:把含有中文的文件另存为utf8格式,即可解决(这个我没测试过);

但是就很麻烦,当然可以把所有的文字定义成变量,放到一个头文件里面,那么要改编码的就只有一个头文件了,这样看起来稍微优雅了点。但是还是很不爽,不能实现国际化。

 

其实直接把文字写在代码里面是一件很不值得推崇的方式(当然图简便还是可以的,但你需要知道他以后会带来的麻烦会很大),我们应该把文字独立出来,不跟我们的代码参合,就像Android的string.xml一样(是不是一下点醒了你?)。

 

于是解决方案2:

我们把所有的文字写到一个配置文件里面,我们程序直接根据key就获取到了utf8的文字,不管当前的源文件是不是utf8的格式的,因为他们不再相干了。请慢慢往下面看。

对于配置文件,我选择json格式(为什么选择json,没原因,就喜欢json,干净利落)。

下面给出例子:

我的json的中文配置文档:

image(图片不能放大??)

image

里面就是简单的json格式的配置文档(关于不懂json的,我后面会写一篇json的解析的文章,目前先不管,或者你们也可以用其他的格式,比如xml,这样cocos2dx已经有解析方案了,原理是一样的)。

 

下面就是我们json解析和使用的代码了(LFString.h和cpp):

#pragma once
#include <string>
#include "json/json.h"
#include "LFFileUtiles.h"
#include <map>

using namespace std;

/**
*    字符串工具,是中文字符的键值对
*/
class LFStrings
{
public:
    static bool init();
    static string getValue(string _key);
    static bool haveValue(string _key);
private:

    static bool parseFile(string relativePath);

    static map<string,string> data;
};

 

 

------cpp

#include "LFStrings.h"

#define ROOT_PATH    "config/"
#define FILE_MAIN    "strings.txt"

// 所支持的标签
#define LABLE_KEY        "key"
#define LABLE_VALUE        "value"
#define LABLE_INCLUDE    "include"

map<string,string> LFStrings::data;

// 用于缓存已经解析了的文件
static map<string,int> paresedFile;

bool LFStrings::init()
{
    data.clear();
    paresedFile.clear();
    return parseFile(FILE_MAIN);
}

bool LFStrings::parseFile(string relativePath)
{
    // 看是否已经解析过了
    if (paresedFile.find(relativePath) != paresedFile.end())
    {
        CCLog("Waring : %s --> file[%s] is pared over before or is in parsing now ,do you include it again???",__FUNCTION__,relativePath.c_str());
        return true;
    }
    paresedFile.insert(pair<string, int>(relativePath,0));


    string path = string(ROOT_PATH)+relativePath;
    CCLog("%s parsing file [%s] ....",__FUNCTION__,path.c_str());

    Json::Reader reader;
    Json::Value root;
    unsigned long size;
    const char* doc = LFFileUtiles::getLFFileUtiles()->readResourceFile(path,&size);
    if (size == 0)
    {
        CCLog("%s ----> file [%s] have no content.",__FUNCTION__,path.c_str());
        return true;
    }

    if (doc == NULL)
    {
        CCLog("%s ----> doc is NULL , open Error!",__FUNCTION__,path.c_str());
        return false;
    }

    if (!reader.parse(doc,root))
    {
        CCLog("%s ----> reader.parse failed! [%s]",__FUNCTION__,path.c_str());
        CCLog(doc);
        delete [] doc;
        CCAssert(false,"");
        return false;
    }

    //CCLog(doc);
    Json::Value _strings= root["strings"];
    if (!_strings.isNull() && _strings.isArray())
    {
        int _stringNum = _strings.size();
        for (int i=0;i<_stringNum;i++)
        {
            Json::Value onePair = _strings[i];
            // 校验
            if(!onePair[LABLE_KEY].isNull() && onePair[LABLE_VALUE].isNull())
            {
                CCLog("Error : %s there is no %s for %s [%s]",__FUNCTION__,LABLE_VALUE,LABLE_KEY,onePair[LABLE_KEY].asCString());
                CCAssert(false,"key 和 value 没有配对");
                continue;
            }
            if(!onePair[LABLE_VALUE].isNull() && onePair[LABLE_KEY].isNull())
            {
                CCLog("Error : %s there is no %s for %s [%s]",__FUNCTION__,LABLE_KEY,LABLE_VALUE,onePair[LABLE_VALUE].asCString());
                CCAssert(false,"key 和 value 没有配对");
                continue;
            }


            //有include
            if (!onePair[LABLE_INCLUDE].isNull())
            {
                string file = onePair[LABLE_INCLUDE].asString();
                if (!parseFile(file))
                {
                    CCLog("Error : %s parse file %s faild",__FUNCTION__,file.c_str());
                    return false;
                }
            }
            // 解析键值对
            if (!onePair[LABLE_KEY].isNull() && !onePair[LABLE_VALUE].isNull())
            {
                string _key = onePair[LABLE_KEY].asString();
                string _value = onePair[LABLE_VALUE].asString();

                if (haveValue(_key))
                {
                    CCLog("Waring : %s --> the key [%s] in file[%s] is already used before,we will ignore this key and value[%s]!",__FUNCTION__,_key.c_str(),path.c_str(),_value.c_str());
                    continue;
                }
                data.insert(pair<string, string>(_key,_value));
            }
        }
    }

    return true;
}

string LFStrings::getValue(string _key)
{
    map<string, string>::iterator iter;
    //如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器;
    iter = data.find(_key);
    if(iter != data.end())
    {
        return iter->second;
    }
    CCLog("Waring : LFStrings::getValue --> _key[%s] is not found!",_key.c_str());
    return "";
}

bool LFStrings::haveValue(string _key)
{
    map<string, string>::iterator iter;
    //如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器;
    iter = data.find(_key);
    return iter != data.end();
}

 

使用方法很简单,游戏启动的时候调用:

// 初始化
LFStrings::init();

他就会找Resource下面的config下面的string.txt文件,进行初始化。

每次要用中文的时候直接:LFStrings::getValue(“biaoti”);// 取得标题字符串

即可。这样就轻松实现中文了,以后直接配置,修改就是了。

 

最后一个问题,怎么实现国际化:

需呀稍微修改下LFStrings类,直接让他解析不同的配置文件就是了,其他的所有代码就不用改。就可以实现语言的动态切换了。

 

明白了吧?

转载于:https://my.oschina.net/u/238958/blog/214221

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值