import { _decorator, CCString, Component, error, Label, RichText } from "cc"; import { EDITOR } from "cc/env"; import { EventName } from "../EventName"; import { eventsOnLoad, preloadEvent } from "../Events"; import I18n from "./I18n"; const { ccclass, property, executeInEditMode, menu } = _decorator; @ccclass @eventsOnLoad() @executeInEditMode @menu("Framework/I18N/LocalizedLabel") export default class LocalizedLabel extends Component { @property(CCString) private _textKey: string = ""; @property({ type: CCString, tooltip: "i18n key" }) public get textKey(): string { return this._textKey; } public set textKey(key: string) { this._textKey = key; this.updateLabel(); } /** * 用于正则替换的配置 */ private _option: { [k: string]: string | number } | Array = []; private _label: Label | RichText = null; public get label(): Label | RichText { if (!this._label) { this._label = this.node.getComponent(Label) || this.node.getComponent(RichText); if (!this._label) { error("Failed to update localized label, label component is invalid!"); return null; } } return this._label; } protected onLoad(): void { try { I18n.init(); this.updateLabel(); } catch (err) { error(err); } } protected update(): void { if (EDITOR) { if (this.label.string) { let key = I18n.getKeyByValue(this.label.string); if (key) { this.textKey = key; } } } } /** * 更新语言 */ @preloadEvent(EventName.UPDATE_LOCALIZED_CMPT) public updateLabel(): void { let localizedString = this._option instanceof Array ? I18n.getText(this._textKey, ...this._option) : I18n.getText(this._textKey, this._option); if (localizedString) { localizedString = this.replaceLabelString(localizedString, this._option instanceof Array ? this._option : []); this.label.string = localizedString; } } /** * 用于动态替换文本中的占位符 * @param text 原始文本 * @param options 替换占位符的值 */ private replaceLabelString(text: string, options: Array): string { // 使用正则表达式匹配 @ 符号作为占位符 let replacedText = text.replace(/@\{(\d+)\}/g, (match, index) => { let replacement = options[parseInt(index) - 1]; return replacement !== undefined ? String(replacement) : match; }); return replacedText; } /** * 设置语言与配置 * @param key * @param option */ public setTextKeyAndOption(key: string, ...option: [{ [k: string]: string | number }] | Array): void { this._textKey = key; this.setOption(...option); } /** * 仅设置配置 * @param option */ public setOption(...option: [{ [k: string]: string | number }] | Array): void { if (option.length === 1 && typeof option[0] === 'object' && !Array.isArray(option[0])) { this._option = option[0] as { [k: string]: string | number }; } else { this._option = option as Array; } this.updateLabel(); } /** * 清除key */ public clear(): void { this.label.string = ""; this.textKey = ""; } }