LocalizedLabel.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { _decorator, CCString, Component, error, Label, RichText } from "cc";
  2. import { EDITOR } from "cc/env";
  3. import { EventName } from "../EventName";
  4. import { eventsOnLoad, preloadEvent } from "../Events";
  5. import I18n from "./I18n";
  6. const { ccclass, property, executeInEditMode, menu } = _decorator;
  7. @ccclass
  8. @eventsOnLoad()
  9. @executeInEditMode
  10. @menu("Framework/I18N/LocalizedLabel")
  11. export default class LocalizedLabel extends Component {
  12. @property(CCString) private _textKey: string = "";
  13. @property({ type: CCString, tooltip: "i18n key" })
  14. public get textKey(): string { return this._textKey; }
  15. public set textKey(key: string) {
  16. this._textKey = key;
  17. this.updateLabel();
  18. }
  19. /**
  20. * 用于正则替换的配置
  21. */
  22. private _option: { [k: string]: string | number } | Array<string | number> = [];
  23. private _label: Label | RichText = null;
  24. public get label(): Label | RichText {
  25. if (!this._label) {
  26. this._label = this.node.getComponent(Label) || this.node.getComponent(RichText);
  27. if (!this._label) {
  28. error("Failed to update localized label, label component is invalid!");
  29. return null;
  30. }
  31. }
  32. return this._label;
  33. }
  34. protected onLoad(): void {
  35. try {
  36. I18n.init();
  37. this.updateLabel();
  38. } catch (err) {
  39. error(err);
  40. }
  41. }
  42. protected update(): void {
  43. if (EDITOR) {
  44. if (this.label.string) {
  45. let key = I18n.getKeyByValue(this.label.string);
  46. if (key) {
  47. this.textKey = key;
  48. }
  49. }
  50. }
  51. }
  52. /**
  53. * 更新语言
  54. */
  55. @preloadEvent(EventName.UPDATE_LOCALIZED_CMPT)
  56. public updateLabel(): void {
  57. let localizedString = this._option instanceof Array ? I18n.getText(this._textKey, ...this._option) : I18n.getText(this._textKey, this._option);
  58. if (localizedString) {
  59. localizedString = this.replaceLabelString(localizedString, this._option instanceof Array ? this._option : []);
  60. this.label.string = localizedString;
  61. }
  62. }
  63. /**
  64. * 用于动态替换文本中的占位符
  65. * @param text 原始文本
  66. * @param options 替换占位符的值
  67. */
  68. private replaceLabelString(text: string, options: Array<string | number>): string {
  69. // 使用正则表达式匹配 @ 符号作为占位符
  70. let replacedText = text.replace(/@\{(\d+)\}/g, (match, index) => {
  71. let replacement = options[parseInt(index) - 1];
  72. return replacement !== undefined ? String(replacement) : match;
  73. });
  74. return replacedText;
  75. }
  76. /**
  77. * 设置语言与配置
  78. * @param key
  79. * @param option
  80. */
  81. public setTextKeyAndOption(key: string, ...option: [{ [k: string]: string | number }] | Array<string | number>): void {
  82. this._textKey = key;
  83. this.setOption(...option);
  84. }
  85. /**
  86. * 仅设置配置
  87. * @param option
  88. */
  89. public setOption(...option: [{ [k: string]: string | number }] | Array<string | number>): void {
  90. if (option.length === 1 && typeof option[0] === 'object' && !Array.isArray(option[0])) {
  91. this._option = option[0] as { [k: string]: string | number };
  92. } else {
  93. this._option = option as Array<string | number>;
  94. }
  95. this.updateLabel();
  96. }
  97. /**
  98. * 清除key
  99. */
  100. public clear(): void {
  101. this.label.string = "";
  102. this.textKey = "";
  103. }
  104. }