热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CocosCreator中的多语言支持实现

在项目需要国际化处理时,即支持多种语言切换的功能,通常有两种方案:单个包和多个包。本文将重点讨论单个包的实现方法。

在项目需要国际化处理时,即支持多种语言切换的功能,通常有两种方案:

单个包

优点:

1. 可以动态切换语言(需要代码支持)

2. 只有一个版本,便于维护

缺点:

1. 安装包较大

多个包

优点:

1. 安装包较小

2. 可以对不同语言进行深度本地化(如功能差异)

缺点:

1. 需要多次提交审核

2. 多个版本的维护成本较高

下面我们重点讨论单个包的实现方法

由于 CocosCreator 内置的 i18n 功能可能不够灵活,因此我们需要自定义一个多语言处理系统。具体实现需要以下几个文件:

1. LanguageMgr.ts

2. LanguageSprite.ts

3. LanguageLabel.ts

4. language.json

以下是各文件的具体实现:

LanguageMgr.ts:

/*
多语言管理类,主要功能是加载多语言的图片和文字
*/
import { EventMgr } from "./EventMgr";
import { GlobalEvent } from "../model/EventType";
import { config } from "./config";
import { CallNative } from "./CallNative";
import { LanguageEnum } from "./Enum";

export class LanguageMgr {
    static languageJson = null;
    static kind = "EN";

    /**
     * 加载多语言json
     */
    static initLanguageJson() {
        this.languageJson = config.getOneConfig("language");
    }

    static init() {
        this.initLanguageJson();
        let kind = "EN";
        if (cc.sys.localStorage.getItem("lanAndCountry")) {
            kind = cc.sys.localStorage.getItem("lanAndCountry");
        } else {
            let lanAndCountry = CallNative.getLanguage();
            if (lanAndCountry.substr(0, 2) === "zh") {
                kind = LanguageEnum.tc;
            } else {
                kind = LanguageEnum.en;
            }
        }
        this.setKind(kind);
    }

    /**
     * 设置语言类型
     * @param kind 
     */
    static setKind(kind: string) {
        this.kind = kind;
    }

    /**
     * 获取当前语言类型
     * @param kind
     */
    static getKind() {
        return this.kind;
    }

    /**
     * 修改语言
     * @param kind 
     */
    static changeLanguage = function (kind: string) {
        if (this.kind !== kind) {
            this.setKind(kind);
            cc.sys.localStorage.setItem("lanAndCountry", kind);
            EventMgr.sendNormalEvent(GlobalEvent.CHANGE_LANGUAGE);
        }
    }

    /**
     * 获取语言包的key
     * @param text 
     * @param param 
     */
    static getText = function (text: string, param?: { "$param1": string | number }) {
        if (this.languageJson && this.languageJson[text]) {
            let str: string = this.languageJson[text][this.kind] || "";
            if (param) {
                if (param["$param1"] !== undefined) str = str.replace("$param1", param["$param1"].toString());
            }
            return str;
        } else if (text === "") {
            return "";
        } else {
            console.log("文本 " + text + " 没有多语言");
            return text;
        }
    }
}

LanguageSprite.ts:

import { LanguageMgr } from "../common/LanguageMgr";
import { GlobalEvent } from "../model/EventType";

const { ccclass, property, menu, requireComponent, disallowMultiple } = cc._decorator;

/**
 * 多语言的图片初始化
 */
@ccclass
@menu("多语言/sprite")
@requireComponent(cc.Sprite)
@disallowMultiple
export default class LanguageSprite extends cc.Component {
    @property(cc.SpriteFrame)
    en: cc.SpriteFrame = null;

    @property(cc.SpriteFrame)
    sc: cc.SpriteFrame = null;

    @property(cc.SpriteFrame)
    tc: cc.SpriteFrame = null;

    start() {
        cc.director.on(GlobalEvent.CHANGE_LANGUAGE, this.changeLanguage, this);
        this.changeLanguage();
    }

    /**
     * 监听切换语言事件
     */
    changeLanguage() {
        if (LanguageMgr.getKind() === "EN") {
            this.getComponent(cc.Sprite).spriteFrame = this.en;
        } else if (LanguageMgr.getKind() === "TC") {
            this.getComponent(cc.Sprite).spriteFrame = this.tc;
        } else {
            if (this.sc) {
                this.getComponent(cc.Sprite).spriteFrame = this.sc;
            } else {
                this.getComponent(cc.Sprite).spriteFrame = this.tc;
            }
        }
    }
}

LanguageLabel.ts:

import { GlobalEvent } from "../model/EventType";
import { LanguageMgr } from "../common/LanguageMgr";

const { ccclass, property, menu, requireComponent, disallowMultiple } = cc._decorator;

@ccclass
@menu("多语言/label")
@requireComponent(cc.Label)
@disallowMultiple
export default class LanguageLabel extends cc.Component {
    // LIFE-CYCLE CALLBACKS:

    @property
    prefix: string = "";

    @property
    suffix: string = "";

    @property
    text: string = "";

    start() {
        cc.director.on(GlobalEvent.CHANGE_LANGUAGE, this.changeLanguage, this);
        this.changeLanguage();
    }

    /**
     * 监听切换语言事件
     */
    changeLanguage() {
        var label = this.getComponent(cc.Label);
        if (label) {
            label.string = this.prefix + LanguageMgr.getText(this.text) + this.suffix;
        } else {
            console.log(this.node.name + " 挂载的节点没有label组件!");
        }
    }
}

language.json:

{
    "TEST_VERSION": {
        "EN": "Test Version",
        "TC": "測試版本",
        "SC": "测试版本"
    },
    "SERVER_IS_DISCONNTECTED_LOGIN_IN_AGAIN": {
        "EN": "The Server is Disconnected, Please Log In Again!",
        "TC": "伺服器已斷開鏈接,請重新登錄!",
        "SC": "服务器已断开连接,请重新登录!"
    },
    "DAILY_TASK": {
        "EN": "Daily Quest",
        "TC": "每日任務!",
        "SC": "每日任务!"
    },
    "OCCUPIED": {
        "EN": "Occupied",
        "TC": "使用中",
        "SC": "使用中"
    }
}

各个脚本的主要用法:

例如,LanguageMgr.getText("TEST_VERSION"); 当文本是动态变化时,需要使用 LanguageMgr.getText 方法。

如果是静态文本显示,则将 LanguageLabel 组件挂载到相应节点。

LanguageSprite 的使用方式与 LanguageLabel 类似。


推荐阅读
author-avatar
采蘑菇的小熙熙_395
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有