多语言对于游戏程序的设计来说是很必要的,很意外的是在cocos命令行项目中也发现了这个,就试着分析一下,不喜勿喷。
主体程序是/bin/目录下的MultiLanguage.py和string.json
一 . 用法
#设置语言类型,本例中时'en','zh','zh_tr' 对应英语,简体,台湾
MultiLanguage.set_language('zh')
#获取相应的字符串
MultiLanguage.get_string('COCOS_PARSE_PLUGIN_WARNING_FMT', classname)
二. 分析
首先应该区分在python中的 类方法和 实例方法(详情链接)
第一个初始化的方法是不能少的,读取语言的配置信息
def __init__(self):
# 获取配置文件的路径
cfg_file_path = os.path.join(get_current_path(), MultiLanguage.CONFIG_FILE_NAME)
try:
# 获取语言和编码方式
sys_lang, self.encoding = locale.getdefaultlocale()
except:
sys_lang = None
self.encoding = None
pass
if self.encoding is None:
self.encoding = 'utf-8'
if sys_lang is None:
cur_lang_key = MultiLanguage.DEFAULT_LANGUAGE
else:
cur_lang_key = self.get_lang_key(sys_lang)
# 读取json文档
if os.path.isfile(cfg_file_path):
f = open(cfg_file_path)
self.cfg_info = json.load(f, encoding='utf-8')
f.close()
if self.cfg_info.has_key(cur_lang_key):
self.cur_lang_strings = self.cfg_info[cur_lang_key]
else:
self.cur_lang_strings = None
if self.cfg_info.has_key(MultiLanguage.DEFAULT_LANGUAGE):
self.default_lang_strings = self.cfg_info[MultiLanguage.DEFAULT_LANGUAGE]
else:
self.default_lang_strings = None
else:
self.cfg_info = None
self.cur_lang_strings = None
self.default_lang_strings = None
def get_current_path():
if getattr(sys, 'frozen', None):
# 获取安装目录
ret = os.path.realpath(os.path.dirname(sys.executable))
else:
# 获取当前文件的目录
ret = os.path.realpath(os.path.dirname(__file__))
return ret
def get_lang_key(self, sys_lang):
# 将系统的语言编号变为自定义的编号
sys_lang_info = sys_lang.split('_')
lang = sys_lang_info[0]
lang = lang.lower()
region = None
if len(sys_lang_info) > 1:
region = sys_lang_info[1]
region = region.lower()
if lang == 'zh':
if (region is None) or (region == 'cn'):
ret = lang
else:
ret = 'zh_tr'
else:
ret = lang
return ret
第二个 set_language
@classmethod
def set_language(cls, lang):
'''
挺常用的设计思路 单体类,调用实例方法设置当前的语言
'''
cls.get_instance().set_current_language(lang)
@classmethod
def get_instance(cls):
if cls.instance is None:
cls.instance = MultiLanguage()
return cls.instance
def set_current_language(self, lang):
if (self.cfg_info is not None) and (self.cfg_info.has_key(lang)):
self.cur_lang_strings = self.cfg_info[lang]
else:
cocos.Logging.warning(MultiLanguage.get_string('COCOS_WARNING_LANG_NOT_SUPPORT_FMT', lang))
第三个: get_string()
@classmethod
def get_string(cls, key, fmt_value=None):
'''
获取指定key的字符,或是返回默认值
'''
fmt = cls.get_instance().get_current_string(key)
if fmt_value is None:
ret = fmt
else:
# 拼凑字段 eg: ("%s,%s") %("name","nID") == "name,nID"
if isinstance(fmt_value, tuple):
dst_values = []
for value in fmt_value:
# 转换编码方式
if isinstance(value, unicode):
dst_values.append(value.encode(cls.get_instance().get_encoding()))
else:
dst_values.append(value)
ret = fmt % tuple(dst_values)
elif isinstance(fmt_value, unicode):
ret = fmt % fmt_value.encode(cls.get_instance().get_encoding())
else:
ret = fmt % fmt_value
return ret
def get_current_string(self, key):
if self.has_key(key, self.cur_lang_strings):
# 查询到含有所需的字段
ret = self.cur_lang_strings[key]
elif self.has_key(key, self.default_lang_strings):
# 查询到默认表中含有所需的字段
ret = self.default_lang_strings[key]
else:
ret= key
# 转换编码方式
if isinstance(ret, unicode):
ret = ret.encode(self.encoding)
return ret
def has_key(self, key, strings_info):
ret = False
if strings_info is not None and strings_info.has_key(key):
ret = True
return ret
三. 总结
该类的核心方法MultiLanguage.get_string().设计思路也是多语言实现的可行方法之一,值得借鉴。另外类中对编码的转换值得注意
有些方法还是值得借鉴的:
#判读表中是否含有键值key
def has_key(self, key, strings_info):
ret = False
if strings_info is not None and strings_info.has_key(key):
ret = True
return ret
# 转换编码方式
if isinstance(ret, unicode):
ret = ret.encode(self.encoding)
# 获取当前文件的目录
def get_current_path():
if getattr(sys, 'frozen', None):
# 获取安装目录
ret = os.path.realpath(os.path.dirname(sys.executable))
else:
# 获取当前文件的目录
ret = os.path.realpath(os.path.dirname(__file__))
return ret
# 获取语言和编码方式
try:
sys_lang, self.encoding = locale.getdefaultlocale()
except:
sys_lang = None
self.encoding = None
pass