Here I want to share multiple language mechanism that I use for my games.
Preface
The main idea is to store text file with translation data as a resource. During runtime we are going to load appropriate language file and get required string by its unique key.
LanguageManager implementation
For that purposes lets create shared singleton class LanguageManager:
#ifndef LanguageManager_h
#define LanguageManager_h
#include <string>
using std::string;
#include "cocos2d.h"
USING_NS_CC;
#include "cocos-ext.h"
using namespace rapidjson; // library that we use for json parsing
class LanguageManager
{
Document document; // current document with language data
LanguageManager(); // constructor is private
static LanguageManager* _instance;
public:
static LanguageManager* getInstance();
string getStringForKey(string key);
};
#endif
And the source file:
#include "LanguageManager.h"
LanguageManager* LanguageManager::_instance = 0;
LanguageManager::LanguageManager()
{
string fileName;
// detect current language
switch(CCApplication::sharedApplication()->getCurrentLanguage())
{
case kLanguageEnglish:
fileName = "en.json";
break;
case kLanguageRussian:
fileName = "ru.json";
break;
default:
CCLOG("Unknown language. Use english");
fileName = "en.json";
break;
};
// below we open, read and parse language data file with rapidjson library
unsigned long size;
const char* buf = (const char*)CCFileUtils::sharedFileUtils()->getFileData(fileName.c_str(), "r", &size);
string content(buf);
string clearContent = content.substr(0, content.rfind('}') + 1);
document.Parse<0>(clearContent.c_str());
if(document.HasParseError())
{
CCLOG("Language file parsing error!");
return;
}
}
LanguageManager* LanguageManager::getInstance()
{
if(!_instance)
_instance = new LanguageManager();
return _instance;
}
string LanguageManager::getStringForKey(string key)
{
return document[key.c_str()].GetString();
}
Usage example:
There is an example of LanguageManager usage from my project:
CCLabelTTF* pauseLabel = CCLabelTTF::create(
LanguageManager::getInstance()->getStringForKey("pause_layer_pause_title").c_str(),
fontName,
titleFontSize);
pauseLabel->setAnchorPoint(CCPoint(0.5, 0.5));
pauseLabel->setPosition(CCPoint(
0.5 * visibleSize.width,
0.65 * visibleSize.height) + origin);
addChild(pauseLabel);
Languange data file example:
en.json
{
"main_menu_play_button_label":"Play",
"mode_selection_menu_label":"Select mode",
"pause_layer_pause_title":"Pause"
}
ru.json
{
"main_menu_play_button_label":"Играть",
"mode_selection_menu_label":"Выберете режим",
"pause_layer_pause_title":"Пауза"
}
LanguageManager is adapted for version 2 but can be easily modified for version 3.