Complete Cocos Creator port with level bundles, themes, and tooling.
Adds level prefabs, theme assets, audio, extensions, and deployment scripts for the Unity WebGL migration. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
12
extensions/localization-editor/static/assets/components.meta
Normal file
12
extensions/localization-editor/static/assets/components.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "e20945fc-1f04-4216-a044-2652e1ebdf78",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
import { _decorator, CCBoolean, CCInteger, CCString, Enum, Label } from 'cc';
|
||||
// @ts-ignore
|
||||
import { EDITOR } from 'cc/env';
|
||||
// import ICUType from '../core/ICUType';
|
||||
// import I18nComponent from './I18nComponent';
|
||||
// import { DateTimeFormatOptions, NumberFormatOptions, RelativeTimeFormatOptions, RelativeTimeFormatUnit } from '../core/ICUOptions';
|
||||
// import intl from '../core/IntlManager';
|
||||
|
||||
const {
|
||||
ccclass,
|
||||
property,
|
||||
requireComponent,
|
||||
executeInEditMode,
|
||||
} = _decorator;
|
||||
|
||||
enum VirtualEnum {}
|
||||
|
||||
// @ccclass('ICUComponent')
|
||||
// @executeInEditMode(true)
|
||||
// @requireComponent(Label)
|
||||
// export default class ICUComponent extends I18nComponent {
|
||||
// @property({ visible: false })
|
||||
// _icuValue = '';
|
||||
//
|
||||
// @property
|
||||
// set icuValue(value: string) {
|
||||
// this._icuValue = value;
|
||||
// this.render();
|
||||
// }
|
||||
//
|
||||
// get icuValue(): string {
|
||||
// return this._icuValue;
|
||||
// }
|
||||
//
|
||||
// @property({ visible: false })
|
||||
// _type: ICUType = ICUType.DateTime;
|
||||
//
|
||||
// @property({ visible: true, type: Enum(ICUType) })
|
||||
// set type(value: ICUType) {
|
||||
// this._type = value;
|
||||
// }
|
||||
//
|
||||
// get type(): ICUType {
|
||||
// return this._type;
|
||||
// }
|
||||
//
|
||||
// protected onLoad() {
|
||||
// super.onLoad();
|
||||
// if (this.label && !this._icuValue) {
|
||||
// this._icuValue = this.label.string;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// protected start() {
|
||||
// this.render();
|
||||
// }
|
||||
//
|
||||
// public render() {
|
||||
// super.render();
|
||||
// if (this._icuValue.length === 0) return;
|
||||
// let translatedString!: string;
|
||||
// try {
|
||||
// switch (this.type) {
|
||||
// case ICUType.Number:
|
||||
// translatedString = intl.tn(parseFloat(this.icuValue), this.numberFormatOptions);
|
||||
// break;
|
||||
// case ICUType.DateTime:
|
||||
// translatedString = intl.td(new Date(this.icuValue), this.dateTimeFormatOptions);
|
||||
// break;
|
||||
// case ICUType.RelativeTime:
|
||||
// translatedString = intl.tt(
|
||||
// parseFloat(this.icuValue),
|
||||
// this.relativeTimeUnit,
|
||||
// this.relativeTimeFormatOptions,
|
||||
// );
|
||||
// break;
|
||||
// case ICUType.List: {
|
||||
// const icuList = this.icuValue.split(',');
|
||||
// translatedString = intl.tl(icuList);
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// } catch (e) {
|
||||
// translatedString = this._icuValue;
|
||||
// }
|
||||
// if (EDITOR) {
|
||||
// this.preview(translatedString);
|
||||
// } else {
|
||||
// this.label!.string = translatedString;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ auto generate by script don't edit ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
||||
// /************************** NumberFormatOptions **************************/
|
||||
// @property({ visible: false })
|
||||
// numberFormatOptions: NumberFormatOptions = { useGrouping: false };
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set numberStyle(value: string) {
|
||||
// this.numberFormatOptions.style = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get numberStyle(): string {
|
||||
// return this.numberFormatOptions.style as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCString,
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set currency(value: string) {
|
||||
// this.numberFormatOptions.currency = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get currency(): string {
|
||||
// return this.numberFormatOptions.currency as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set currencySign(value: string) {
|
||||
// this.numberFormatOptions.currencySign = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get currencySign(): string {
|
||||
// return this.numberFormatOptions.currencySign as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set currencyDisplay(value: string) {
|
||||
// this.numberFormatOptions.currencyDisplay = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get currencyDisplay(): string {
|
||||
// return this.numberFormatOptions.currencyDisplay as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCBoolean,
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set useGrouping(value: boolean) {
|
||||
// this.numberFormatOptions.useGrouping = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get useGrouping(): boolean {
|
||||
// return this.numberFormatOptions.useGrouping as boolean;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCInteger,
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set minimumIntegerDigits(value: number) {
|
||||
// this.numberFormatOptions.minimumIntegerDigits = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get minimumIntegerDigits(): number {
|
||||
// return this.numberFormatOptions.minimumIntegerDigits as number;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCInteger,
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set minimumFractionDigits(value: number) {
|
||||
// this.numberFormatOptions.minimumFractionDigits = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get minimumFractionDigits(): number {
|
||||
// return this.numberFormatOptions.minimumFractionDigits as number;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCInteger,
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set maximumFractionDigits(value: number) {
|
||||
// this.numberFormatOptions.maximumFractionDigits = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get maximumFractionDigits(): number {
|
||||
// return this.numberFormatOptions.maximumFractionDigits as number;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCInteger,
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set minimumSignificantDigits(value: number) {
|
||||
// this.numberFormatOptions.minimumSignificantDigits = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get minimumSignificantDigits(): number {
|
||||
// return this.numberFormatOptions.minimumSignificantDigits as number;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCInteger,
|
||||
// group: 'Number',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.Number;
|
||||
// },
|
||||
// })
|
||||
// set maximumSignificantDigits(value: number) {
|
||||
// this.numberFormatOptions.maximumSignificantDigits = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get maximumSignificantDigits(): number {
|
||||
// return this.numberFormatOptions.maximumSignificantDigits as number;
|
||||
// }
|
||||
//
|
||||
// /************************** DateTimeFormatOptions **************************/
|
||||
// @property({ visible: false })
|
||||
// dateTimeFormatOptions: DateTimeFormatOptions = {};
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set dateTimeLocaleMatcher(value: string) {
|
||||
// this.dateTimeFormatOptions.localeMatcher = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get dateTimeLocaleMatcher(): string {
|
||||
// return this.dateTimeFormatOptions.localeMatcher as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set weekday(value: string) {
|
||||
// this.dateTimeFormatOptions.weekday = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get weekday(): string {
|
||||
// return this.dateTimeFormatOptions.weekday as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set era(value: string) {
|
||||
// this.dateTimeFormatOptions.era = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get era(): string {
|
||||
// return this.dateTimeFormatOptions.era as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set year(value: string) {
|
||||
// this.dateTimeFormatOptions.year = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get year(): string {
|
||||
// return this.dateTimeFormatOptions.year as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set month(value: string) {
|
||||
// this.dateTimeFormatOptions.month = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get month(): string {
|
||||
// return this.dateTimeFormatOptions.month as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set day(value: string) {
|
||||
// this.dateTimeFormatOptions.day = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get day(): string {
|
||||
// return this.dateTimeFormatOptions.day as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set hour(value: string) {
|
||||
// this.dateTimeFormatOptions.hour = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get hour(): string {
|
||||
// return this.dateTimeFormatOptions.hour as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set minute(value: string) {
|
||||
// this.dateTimeFormatOptions.minute = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get minute(): string {
|
||||
// return this.dateTimeFormatOptions.minute as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set second(value: string) {
|
||||
// this.dateTimeFormatOptions.second = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get second(): string {
|
||||
// return this.dateTimeFormatOptions.second as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set timeZoneName(value: string) {
|
||||
// this.dateTimeFormatOptions.timeZoneName = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get timeZoneName(): string {
|
||||
// return this.dateTimeFormatOptions.timeZoneName as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set formatMatcher(value: string) {
|
||||
// this.dateTimeFormatOptions.formatMatcher = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get formatMatcher(): string {
|
||||
// return this.dateTimeFormatOptions.formatMatcher as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCBoolean,
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set hour12(value: boolean) {
|
||||
// this.dateTimeFormatOptions.hour12 = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get hour12(): boolean {
|
||||
// return this.dateTimeFormatOptions.hour12 as boolean;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: CCString,
|
||||
// group: 'DateTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.DateTime;
|
||||
// },
|
||||
// })
|
||||
// set timeZone(value: string) {
|
||||
// this.dateTimeFormatOptions.timeZone = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get timeZone(): string {
|
||||
// return this.dateTimeFormatOptions.timeZone as string;
|
||||
// }
|
||||
//
|
||||
// /************************** RelativeTimeOptions **************************/
|
||||
// @property({ visible: false })
|
||||
// relativeTimeFormatOptions: RelativeTimeFormatOptions = {};
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'RelativeTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.RelativeTime;
|
||||
// },
|
||||
// })
|
||||
// set relativeTimeLocaleMatcher(value: string) {
|
||||
// this.relativeTimeFormatOptions.localeMatcher = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get relativeTimeLocaleMatcher(): string {
|
||||
// return this.relativeTimeFormatOptions.localeMatcher as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'RelativeTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.RelativeTime;
|
||||
// },
|
||||
// })
|
||||
// set numeric(value: string) {
|
||||
// this.relativeTimeFormatOptions.numeric = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get numeric(): string {
|
||||
// return this.relativeTimeFormatOptions.numeric as string;
|
||||
// }
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'RelativeTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.RelativeTime;
|
||||
// },
|
||||
// })
|
||||
// set relativeTimeStyle(value: string) {
|
||||
// this.relativeTimeFormatOptions.style = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get relativeTimeStyle(): string {
|
||||
// return this.relativeTimeFormatOptions.style as string;
|
||||
// }
|
||||
//
|
||||
// @property({ visible: false })
|
||||
// _relativeTimeUnit: RelativeTimeFormatUnit = 'second';
|
||||
//
|
||||
// @property({
|
||||
// type: Enum(VirtualEnum),
|
||||
// group: 'RelativeTime',
|
||||
// visible(this: ICUComponent) {
|
||||
// return this.type === ICUType.RelativeTime;
|
||||
// },
|
||||
// })
|
||||
// set relativeTimeUnit(value: string) {
|
||||
// this._relativeTimeUnit = value;
|
||||
// this.render();
|
||||
// }
|
||||
// get relativeTimeUnit(): string {
|
||||
// return this._relativeTimeUnit;
|
||||
// }
|
||||
//
|
||||
// // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ auto generate by script don't edit ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
||||
// }
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "7a970d99-7d42-4b01-895c-a1fd06c411b5",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { _decorator, Component, Label, Node } from 'cc';
|
||||
// @ts-ignore
|
||||
import { EDITOR } from 'cc/env';
|
||||
|
||||
const {
|
||||
ccclass,
|
||||
property,
|
||||
disallowMultiple,
|
||||
requireComponent,
|
||||
menu,
|
||||
} = _decorator;
|
||||
|
||||
@ccclass('L10nComponent')
|
||||
@requireComponent(Label)
|
||||
@disallowMultiple()
|
||||
@menu('hidden:LocalizationEditor/L10nComponent')
|
||||
export default abstract class L10nComponent extends Component {
|
||||
protected constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
@property({
|
||||
readonly: true,
|
||||
tooltip: 'i18n:localization-editor.component.string'
|
||||
})
|
||||
get string() {
|
||||
return this.label?.string || '';
|
||||
}
|
||||
label?: Label | null = undefined;
|
||||
|
||||
protected onLoad() {
|
||||
this.label = this.node.getComponent(Label);
|
||||
}
|
||||
|
||||
protected start() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
public render() {}
|
||||
|
||||
public preview(value: string) {
|
||||
if (this.label && EDITOR) {
|
||||
const originalString = this.label.string;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
this.label._string = value;
|
||||
this.label.updateRenderData(true);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
cce.Engine.repaintInEditMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "64a567b7-70a8-4921-894e-b2b550a6ba6f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// @ts-ignore
|
||||
import { _decorator } from 'cc';
|
||||
// @ts-ignore
|
||||
import { EDITOR } from 'cc/env';
|
||||
import l10n from '../core/l10n-manager';
|
||||
import L10nComponent from './l10n-component';
|
||||
|
||||
const {
|
||||
ccclass,
|
||||
property,
|
||||
executeInEditMode,
|
||||
menu,
|
||||
help,
|
||||
} = _decorator;
|
||||
|
||||
@ccclass('L10nLabel')
|
||||
@executeInEditMode(true)
|
||||
@menu('LocalizationEditor/L10nLabel')
|
||||
@help('i18n:localization-editor.component.help')
|
||||
export default class L10nLabel extends L10nComponent {
|
||||
@property({ visible: false })
|
||||
_key = '';
|
||||
|
||||
@property({
|
||||
tooltip: 'i18n:localization-editor.component.key1'
|
||||
})
|
||||
set key(value: string) {
|
||||
this._key = value;
|
||||
this.render();
|
||||
}
|
||||
|
||||
get key(): string {
|
||||
return this._key;
|
||||
}
|
||||
@property({ visible: false })
|
||||
_count = 0;
|
||||
@property({
|
||||
tooltip: 'i18n:localization-editor.component.count'
|
||||
})
|
||||
set count(value: number) {
|
||||
this._count = value;
|
||||
this.render();
|
||||
}
|
||||
|
||||
get count(): number {
|
||||
return this._count;
|
||||
}
|
||||
|
||||
onLoad() {
|
||||
if (typeof super.onLoad === 'function') {
|
||||
super.onLoad();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const translatedString = l10n.t(this._key, { count: this._count });
|
||||
if (typeof this.label === 'undefined' || typeof translatedString === 'undefined') {
|
||||
return;
|
||||
}
|
||||
if (EDITOR) {
|
||||
this.preview(translatedString);
|
||||
} else {
|
||||
this.label!.string = translatedString;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "30d83ab3-45f6-472d-8305-9f8280f4f1b8",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
13
extensions/localization-editor/static/assets/core.meta
Normal file
13
extensions/localization-editor/static/assets/core.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "ef8d37e0-634c-4106-a3ee-13df564c46a3",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {},
|
||||
"bundleName": "1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "8726de39-9138-4457-8098-f4b669c27882",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import l10n from './l10n-manager';
|
||||
import { game, cclegacy } from 'cc';
|
||||
// @ts-expect-error
|
||||
import { EDITOR } from 'cc/env';
|
||||
if (cclegacy.GAME_VIEW || EDITOR) { // for Editor
|
||||
// @ts-expect-error we need top level await in Editor
|
||||
await l10n.createIntl({});
|
||||
|
||||
} else { // for Runtime or Preview
|
||||
game.onPostProjectInitDelegate.add(
|
||||
() => l10n.createIntl({}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "2f21bc78-8001-4d8f-a75c-b7da831c91c7",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { FallbackLanguage, L10nValue } from './l10n-options';
|
||||
|
||||
export type FormattedValue = string;
|
||||
export type TextInfoDirection = 'ltr' | 'rtl';
|
||||
|
||||
export interface StandardOption {
|
||||
count?: number;
|
||||
// 暂不开放
|
||||
// context?: string
|
||||
defaultValue?: L10nValue;
|
||||
// returnObjects?: boolean;
|
||||
language?: Intl.BCP47LanguageTag;
|
||||
fallbackLanguage?: FallbackLanguage;
|
||||
// 暂不开放
|
||||
// joinArrays?: string
|
||||
}
|
||||
|
||||
export interface Template {
|
||||
[key: string]:
|
||||
| string
|
||||
| {
|
||||
[key: string]: StandardOption;
|
||||
};
|
||||
}
|
||||
|
||||
export interface NumberFormatOptions extends Intl.NumberFormatOptions {
|
||||
style?: 'decimal' | 'percent' | 'currency' | string;
|
||||
/**
|
||||
* 货币代码,采用ISO 4217标准
|
||||
* @see ISO4217Tag
|
||||
*/
|
||||
currency?: string;
|
||||
currencySign?: 'standard' | 'accounting' | string;
|
||||
currencyDisplay?: 'symbol' | 'code' | 'name' | string;
|
||||
useGrouping?: boolean;
|
||||
minimumIntegerDigits?: number;
|
||||
minimumFractionDigits?: number;
|
||||
maximumFractionDigits?: number;
|
||||
minimumSignificantDigits?: number;
|
||||
maximumSignificantDigits?: number;
|
||||
}
|
||||
|
||||
export interface DateTimeFormatOptions {
|
||||
localeMatcher?: 'best fit' | 'lookup' | undefined | string;
|
||||
weekday?: 'long' | 'short' | 'narrow' | undefined | string;
|
||||
era?: 'long' | 'short' | 'narrow' | undefined | string;
|
||||
year?: 'numeric' | '2-digit' | undefined | string;
|
||||
month?: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow' | undefined | string;
|
||||
day?: 'numeric' | '2-digit' | undefined | string;
|
||||
hour?: 'numeric' | '2-digit' | undefined | string;
|
||||
minute?: 'numeric' | '2-digit' | undefined | string;
|
||||
second?: 'numeric' | '2-digit' | undefined | string;
|
||||
timeZoneName?: 'long' | 'short' | undefined | string;
|
||||
formatMatcher?: 'best fit' | 'basic' | undefined | string;
|
||||
hour12?: boolean | undefined;
|
||||
timeZone?: string | undefined;
|
||||
}
|
||||
|
||||
export type RelativeTimeFormatUnit = 'second' | 'minute' | 'hour' | 'day' | 'month' | 'year' | string;
|
||||
|
||||
export interface RelativeTimeFormatOptions {
|
||||
localeMatcher?: 'lookup' | 'best fit' | string;
|
||||
style?: 'narrow' | 'short' | 'long' | string;
|
||||
numeric?: 'auto' | 'always' | string;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "dc153188-b6f7-4234-8025-20163cbd0f8c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Intl formatting
|
||||
*/
|
||||
enum ICUType {
|
||||
DateTime,
|
||||
Number,
|
||||
List,
|
||||
RelativeTime,
|
||||
}
|
||||
|
||||
export default ICUType;
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e5dc4963-9221-45a4-8f4b-a8af210423e5",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
enum L10nListenEvent {
|
||||
languageChanged = 'languageChanged',
|
||||
onMissingKey = 'missingKey',
|
||||
|
||||
/**
|
||||
* store events
|
||||
*/
|
||||
// onAdded = 'added',
|
||||
// onRemoved = 'removed',
|
||||
}
|
||||
|
||||
export default L10nListenEvent;
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "3415306a-cc9f-4b47-8961-2437afa40e1f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { createInstance, i18n, InitOptions as I18NextInitOptions } from 'i18next';
|
||||
// @ts-ignore
|
||||
import { EDITOR, BUILD, PREVIEW } from 'cc/env';
|
||||
// @ts-ignore
|
||||
import { game, assetManager } from 'cc';
|
||||
import type { L10nOptions, ResourceData, L10nKey, L10nValue, ResourceItem } from './l10n-options';
|
||||
import {
|
||||
DateTimeFormatOptions,
|
||||
FormattedValue,
|
||||
NumberFormatOptions,
|
||||
RelativeTimeFormatOptions,
|
||||
RelativeTimeFormatUnit,
|
||||
StandardOption,
|
||||
Template,
|
||||
TextInfoDirection,
|
||||
} from './icu-options';
|
||||
import L10nListenEvent from './l10n-listen-event';
|
||||
import ResourceDataManager from './resource-data-manager';
|
||||
import { mainName, pluginName } from './localization-global';
|
||||
import { ResourceBundle, ResourceList } from './l10n-options';
|
||||
|
||||
export class L10nManager {
|
||||
static LOCAL_STORAGE_LANGUAGE_KEY = `${mainName}/language`;
|
||||
static readonly DEFAULT_NAMESPACE = 'translation' as const;
|
||||
static readonly ASSET_NAMESPACE = 'asset' as const;
|
||||
static readonly ALLOW_NAMESPACE = [L10nManager.DEFAULT_NAMESPACE, L10nManager.ASSET_NAMESPACE] as const;
|
||||
static l10n: L10nManager = new L10nManager();
|
||||
/**
|
||||
* @zh
|
||||
* i18n 实例
|
||||
* @en
|
||||
* i18next instance
|
||||
*/
|
||||
private _intl?: i18n = undefined;
|
||||
|
||||
private _options: L10nOptions = {};
|
||||
|
||||
private resourceList?: ResourceList;
|
||||
|
||||
private resourceBundle: ResourceBundle = {};
|
||||
|
||||
public resourceDataManager: ResourceDataManager;
|
||||
|
||||
private constructor() {
|
||||
this.resourceDataManager = new ResourceDataManager();
|
||||
}
|
||||
|
||||
public isInitialized(): boolean {
|
||||
return this._intl?.isInitialized ?? false;
|
||||
}
|
||||
|
||||
public async createIntl(options: L10nOptions) {
|
||||
const reloadResult = await this.reloadResourceData();
|
||||
if (!reloadResult) {
|
||||
return;
|
||||
}
|
||||
this._options = options;
|
||||
this._intl = createInstance();
|
||||
let localStorageLanguage: string | undefined = undefined;
|
||||
if (BUILD && !PREVIEW) {
|
||||
localStorageLanguage = localStorage.getItem(
|
||||
l10n['_options'].localStorageLanguageKey ?? L10nManager.LOCAL_STORAGE_LANGUAGE_KEY,
|
||||
);
|
||||
localStorageLanguage = this.checkLanguage(localStorageLanguage);
|
||||
}
|
||||
const defaultLanguage = localStorageLanguage ?? options.language ?? this.resourceList.defaultLanguage;
|
||||
const fallbackLanguage = options.fallbackLanguage ?? this.resourceList.fallbackLanguage;
|
||||
const resources = options.resources ?? this.resourceBundle;
|
||||
|
||||
const i18nextOptions: I18NextInitOptions = {
|
||||
lng: defaultLanguage,
|
||||
fallbackLng: fallbackLanguage,
|
||||
resources: { ...resources },
|
||||
ns: L10nManager.ALLOW_NAMESPACE,
|
||||
defaultNS: L10nManager.DEFAULT_NAMESPACE,
|
||||
initImmediate: false,
|
||||
load: 'currentOnly',
|
||||
};
|
||||
await this._intl.init(i18nextOptions);
|
||||
this.setAssetOverrideMap(resources[defaultLanguage][L10nManager.ASSET_NAMESPACE]);
|
||||
|
||||
}
|
||||
|
||||
public checkLanguage(language: string): string | undefined {
|
||||
if (!language || language.length === 0 || language === 'null' || language === null || language === 'undefined' || language === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (this.resourceList && this.resourceList.languages.length > 0 && this.resourceList.languages.find(it => it === language)) {
|
||||
return language;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public cloneIntl(options: L10nOptions) {
|
||||
if (!this._intl) {
|
||||
throw new Error('i18next not init, please use \'l10n.createIntl\'');
|
||||
}
|
||||
this._intl = this._intl.cloneInstance(options);
|
||||
}
|
||||
|
||||
async reloadResourceData(): Promise<boolean> {
|
||||
this.resourceList = await this.resourceDataManager.readResourceList();
|
||||
if (!this.resourceList) {
|
||||
console.log(`[${pluginName}] not found translate language list, skip init l10n`);
|
||||
return false;
|
||||
}
|
||||
this.resourceBundle = await this.resourceDataManager.readResourceBundle(this.resourceList?.languages ?? []);
|
||||
if (!this.resourceList?.defaultLanguage) {
|
||||
console.log(`[${pluginName}] not found translate language data, skip init l10n`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 初始化 i18next */
|
||||
public config(options: L10nOptions) {
|
||||
this.cloneIntl(options);
|
||||
}
|
||||
|
||||
public async changeLanguage(language: Intl.BCP47LanguageTag) {
|
||||
if (!language) {
|
||||
console.warn(`[${pluginName}] invalid language tag`);
|
||||
return;
|
||||
}
|
||||
console.log(`[${pluginName}] will change language to`, language);
|
||||
if (this._intl) {
|
||||
if (this.currentLanguage) {
|
||||
this.releaseOverrideMap();
|
||||
}
|
||||
await this._intl.changeLanguage(language);
|
||||
this.setAssetOverrideMap(this.resourceBundle[language][L10nManager.ASSET_NAMESPACE]);
|
||||
if (!EDITOR) {
|
||||
localStorage.setItem(L10nManager.LOCAL_STORAGE_LANGUAGE_KEY, language);
|
||||
console.log(`[${pluginName}] game will restart`);
|
||||
game.restart();
|
||||
}
|
||||
} else {
|
||||
console.log(`[${pluginName}] language data not load, please confirm whether the language data is included in the build`);
|
||||
}
|
||||
}
|
||||
|
||||
public t(key: L10nKey, options?: StandardOption | Template): L10nValue {
|
||||
if (!(this._intl?.isInitialized ?? false)) return key;
|
||||
return this._intl!.t(key, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实验性功能暂不开放
|
||||
* 数字类ICU
|
||||
*/
|
||||
private tn(value: number, options?: NumberFormatOptions): FormattedValue {
|
||||
if (!(this._intl?.isInitialized ?? false)) return value.toString();
|
||||
const cloneOptions: NumberFormatOptions = {};
|
||||
Object.assign(cloneOptions, options);
|
||||
type NumberFormatOptionsKey = keyof NumberFormatOptions;
|
||||
for (const key of Object.keys(cloneOptions) as NumberFormatOptionsKey[]) {
|
||||
if (typeof cloneOptions[key] === 'string' && (cloneOptions[key] as string)!.length === 0) {
|
||||
delete cloneOptions[key];
|
||||
} else if (typeof cloneOptions[key] === 'number' && cloneOptions[key] === 0) {
|
||||
delete cloneOptions[key];
|
||||
}
|
||||
}
|
||||
return new Intl.NumberFormat(this._intl?.language, cloneOptions).format(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实验性功能暂不开放
|
||||
* 日期/时刻类ICU
|
||||
*/
|
||||
private td(date: Date, options?: DateTimeFormatOptions): FormattedValue {
|
||||
if (!(this._intl?.isInitialized ?? false)) return date.toString();
|
||||
const cloneOptions: DateTimeFormatOptions = {};
|
||||
Object.assign(cloneOptions, options);
|
||||
type DateTimeFormatOptionsKey = keyof DateTimeFormatOptions;
|
||||
for (const key of Object.keys(cloneOptions) as DateTimeFormatOptionsKey[]) {
|
||||
if (typeof cloneOptions[key] === 'string' && (cloneOptions[key] as string).length === 0) {
|
||||
delete cloneOptions[key];
|
||||
}
|
||||
}
|
||||
return new Intl.DateTimeFormat(this._intl?.language, cloneOptions as Intl.DateTimeFormatOptions).format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实验性功能暂不开放
|
||||
* 时长类ICU
|
||||
*/
|
||||
private tt(value: number, unit: RelativeTimeFormatUnit, options?: RelativeTimeFormatOptions): FormattedValue {
|
||||
if (!(this._intl?.isInitialized ?? false)) return value.toString();
|
||||
const cloneOptions: RelativeTimeFormatOptions = {};
|
||||
Object.assign(cloneOptions, options);
|
||||
type RelativeTimeFormatOptionsKey = keyof RelativeTimeFormatOptions;
|
||||
for (const key of Object.keys(cloneOptions) as RelativeTimeFormatOptionsKey[]) {
|
||||
if (typeof cloneOptions[key] === 'string' && (cloneOptions[key] as string).length === 0) {
|
||||
delete cloneOptions[key];
|
||||
}
|
||||
}
|
||||
return new Intl.RelativeTimeFormat(this._intl?.language, cloneOptions as Intl.RelativeTimeFormatOptions).format(
|
||||
value,
|
||||
unit as Intl.RelativeTimeFormatUnit,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实验性功能暂不开放
|
||||
* 数组类ICU
|
||||
*/
|
||||
private tl(value: string[]): FormattedValue {
|
||||
if (!(this._intl?.isInitialized ?? false)) return value.toString();
|
||||
return new Intl.ListFormat(this._intl?.language).format(value);
|
||||
}
|
||||
|
||||
public exists(key: L10nKey): boolean {
|
||||
return this._intl?.exists(key) ?? false;
|
||||
}
|
||||
|
||||
get currentLanguage(): Intl.BCP47LanguageTag {
|
||||
return this._intl?.language ?? '';
|
||||
}
|
||||
|
||||
get languages(): readonly Intl.BCP47LanguageTag[] {
|
||||
return this.resourceList?.languages ?? [];
|
||||
}
|
||||
|
||||
public direction(language?: Intl.BCP47LanguageTag): TextInfoDirection {
|
||||
return (language ? new Intl.Locale(language) : new Intl.Locale(this._intl!.language)).textInfo()
|
||||
.direction as TextInfoDirection;
|
||||
}
|
||||
|
||||
public on(event: L10nListenEvent, callback: (...args: any[]) => void) {
|
||||
this._intl?.on(event, callback);
|
||||
}
|
||||
|
||||
public off(event: L10nListenEvent, callback: (...args: any[]) => void) {
|
||||
this._intl?.off(event, callback);
|
||||
}
|
||||
|
||||
public getResourceBundle(language: string, namespace: typeof L10nManager.ALLOW_NAMESPACE[number]): ResourceData | undefined {
|
||||
return this._intl?.getResourceBundle(language, namespace);
|
||||
}
|
||||
|
||||
protected setAssetOverrideMap(assetNamespace: Readonly<ResourceItem>) {
|
||||
for (const key of Object.keys(assetNamespace)) {
|
||||
assetManager.assetsOverrideMap.set(key, assetNamespace[key]);
|
||||
}
|
||||
}
|
||||
|
||||
protected releaseOverrideMap() {
|
||||
assetManager.assetsOverrideMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
const l10n: L10nManager = L10nManager.l10n;
|
||||
|
||||
export default l10n;
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "2856aec6-495f-456d-be77-9ce8a6277dc9",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
export type L10nKey = string;
|
||||
export type L10nValue = string;
|
||||
|
||||
export interface ResourceList {
|
||||
defaultLanguage?: Intl.BCP47LanguageTag;
|
||||
fallbackLanguage?: Intl.BCP47LanguageTag;
|
||||
languages: Intl.BCP47LanguageTag[];
|
||||
}
|
||||
|
||||
export interface ResourceBundle {
|
||||
[language: Intl.BCP47LanguageTag]: ResourceData;
|
||||
}
|
||||
|
||||
export interface ResourceData {
|
||||
[namespace: string]: ResourceItem;
|
||||
}
|
||||
|
||||
export interface ResourceItem {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface FallbackLanguageObjectList {
|
||||
[language: string]: readonly string[];
|
||||
}
|
||||
|
||||
export type FallbackLanguage =
|
||||
| string
|
||||
| readonly string[]
|
||||
| FallbackLanguageObjectList
|
||||
| ((language: Intl.BCP47LanguageTag) => string | readonly string[] | FallbackLanguageObjectList);
|
||||
|
||||
export interface L10nOptions {
|
||||
/**
|
||||
* Logs info level to console output. Helps finding issues with loading not working.
|
||||
* @default false
|
||||
*/
|
||||
// debug?: boolean;
|
||||
|
||||
/**
|
||||
* Resources to initialize with (if not using loading or not appending using addResourceBundle)
|
||||
* @default undefined
|
||||
*/
|
||||
resources?: ResourceBundle;
|
||||
|
||||
/**
|
||||
* Language to use (overrides language detection)
|
||||
*/
|
||||
language?: Intl.BCP47LanguageTag;
|
||||
|
||||
/**
|
||||
* Language to use if translations in user language are not available.
|
||||
* @default same as language
|
||||
*/
|
||||
fallbackLanguage?: false | FallbackLanguage;
|
||||
|
||||
/**
|
||||
* @default IntlManager.LOCAL_STORAGE_LANGUAGE_KEY
|
||||
*/
|
||||
localStorageLanguageKey?: string;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 可以对key进行前置处理,返回值应该是处理后的key
|
||||
*
|
||||
* @en
|
||||
* Preprocess the key
|
||||
*
|
||||
* @param key
|
||||
* @return string
|
||||
* onBeforeProcessHandler
|
||||
*/
|
||||
beforeTranslate?: (key: L10nKey) => L10nValue;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 对value进行后置处理,返回值应该是处理后的value
|
||||
*
|
||||
* @en
|
||||
* Postprocess the value, return the processed value
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return string
|
||||
*/
|
||||
afterTranslate?: (key: string, value: string) => string;
|
||||
|
||||
/**
|
||||
* Allows null values as valid translation
|
||||
* @default true
|
||||
*/
|
||||
returnNull?: boolean;
|
||||
|
||||
/**
|
||||
* Allows empty string as valid translation
|
||||
* @default true
|
||||
*/
|
||||
returnEmptyString?: boolean;
|
||||
|
||||
/**
|
||||
* Allows objects as valid translation result
|
||||
* @default false
|
||||
*/
|
||||
// returnObjects?: boolean;
|
||||
|
||||
/**
|
||||
* Gets called if object was passed in as key but returnObjects was set to false
|
||||
* @default noop
|
||||
*/
|
||||
// returnedObjectHandler?: (key: string, value: string, options: any) => void;
|
||||
|
||||
/**
|
||||
* Char, eg. '\n' that arrays will be joined by
|
||||
* @default false
|
||||
*/
|
||||
// joinArrays?: false | string;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "b461821b-b11b-4b2d-b469-d9d42b137108",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export const pluginName = 'Localization Editor';
|
||||
export const mainName = 'localization-editor';
|
||||
export const runtimeBundleName = 'l10n';
|
||||
export const resourceListPath = 'resource-list';
|
||||
export const resourceBundlePath = 'resource-bundle';
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "02d9eb4a-80d0-46a8-b3e9-bd4ed15f6f68",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// @ts-ignore
|
||||
import { BUILD, EDITOR } from 'cc/env';
|
||||
import { AssetManager, assetManager, JsonAsset, settings, Settings } from 'cc';
|
||||
import { ResourceBundle, ResourceList } from './l10n-options';
|
||||
import { mainName, pluginName, resourceBundlePath, resourceListPath, runtimeBundleName } from './localization-global';
|
||||
|
||||
export default class ResourceDataManager {
|
||||
async readResourceList(): Promise<ResourceList> {
|
||||
if (EDITOR) {
|
||||
return Editor.Message.request(mainName, 'get-resource-list');
|
||||
} else if (BUILD) {
|
||||
console.log(`[${pluginName}] this is build env`);
|
||||
return this.runtimeLoad(resourceListPath);
|
||||
} else {
|
||||
return this.previewLoad(resourceListPath);
|
||||
}
|
||||
}
|
||||
|
||||
async readResourceBundle(tags: Intl.BCP47LanguageTag[]): Promise<ResourceBundle> {
|
||||
if (EDITOR) {
|
||||
return this.editorLoad(tags);
|
||||
} else if (BUILD) {
|
||||
return this.runtimeLoad(resourceBundlePath);
|
||||
} else {
|
||||
return this.previewLoad(resourceBundlePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑器模式下使用
|
||||
* @param locales
|
||||
*/
|
||||
async editorLoad(locales: Intl.BCP47LanguageTag[]): Promise<ResourceBundle | undefined> {
|
||||
return Editor.Message.request(mainName, 'get-resource-bundle', locales);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建后运行时使用
|
||||
* @param fileName
|
||||
*/
|
||||
async runtimeLoad<T>(fileName: string): Promise<T | undefined> {
|
||||
const bundle = await this.getBundle(runtimeBundleName);
|
||||
if (!bundle) return undefined;
|
||||
const jsonAsset = await this.getResource(bundle, fileName);
|
||||
if (!jsonAsset || !jsonAsset.json) return undefined;
|
||||
return jsonAsset.json as any as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 浏览器预览使用
|
||||
* @param urlPath
|
||||
*/
|
||||
async previewLoad<T>(urlPath: string): Promise<T | undefined> {
|
||||
try {
|
||||
return await (await fetch(`${mainName}/${urlPath}`)).json() as T;
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async checkBundle(bundleName: string): Promise<boolean> {
|
||||
const queryResult: { bundle: string, version: string }[] | null = settings.querySettings<{ bundle: string, version: string }[]>(Settings.Category.ASSETS, 'preloadBundles');
|
||||
const bundle = queryResult?.find((it) => it.bundle === bundleName);
|
||||
return !!bundle;
|
||||
}
|
||||
|
||||
async getBundle(bundleName: string): Promise<AssetManager.Bundle | undefined> {
|
||||
return new Promise(resolve => {
|
||||
assetManager.loadBundle(bundleName, (error, bundle: AssetManager.Bundle) => {
|
||||
if (error) {
|
||||
resolve(undefined);
|
||||
} else {
|
||||
resolve(bundle);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async getResource(bundle: AssetManager.Bundle, resourceName: string): Promise<JsonAsset | undefined> {
|
||||
return new Promise(resolve => {
|
||||
bundle.load(resourceName, (error, asset: JsonAsset) => {
|
||||
if (error) {
|
||||
resolve(undefined);
|
||||
} else {
|
||||
resolve(asset);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "0a95ad24-8abb-499c-99cc-9d959245a167",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
extensions/localization-editor/static/assets/l10n.meta
Normal file
12
extensions/localization-editor/static/assets/l10n.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "5edb8c82-d058-4174-84ae-a6624ae65a90",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"isBundle": true,
|
||||
"bundleConfigID": "default"
|
||||
}
|
||||
}
|
||||
21
extensions/localization-editor/static/assets/l10n.ts
Normal file
21
extensions/localization-editor/static/assets/l10n.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import l10n, { L10nManager } from './core/l10n-manager';
|
||||
import L10nListenEvent from './core/l10n-listen-event';
|
||||
import L10nLabel from './components/l10n-label';
|
||||
export type {
|
||||
L10nKey,
|
||||
L10nValue,
|
||||
ResourceList,
|
||||
ResourceBundle,
|
||||
ResourceData,
|
||||
ResourceItem,
|
||||
FallbackLanguageObjectList,
|
||||
FallbackLanguage,
|
||||
L10nOptions,
|
||||
} from './core/l10n-options';
|
||||
|
||||
export {
|
||||
l10n,
|
||||
L10nManager,
|
||||
L10nLabel,
|
||||
L10nListenEvent,
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "07b549ce-14f5-4964-9fc4-366b956df8d8",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"importer": "json",
|
||||
"imported": true,
|
||||
"uuid": "fa0fa81e-eaf8-4eb4-8a48-181676ceff01",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"importer": "json",
|
||||
"imported": true,
|
||||
"uuid": "d2f18e87-d231-4e20-9e54-06a7aa2bd5c1",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
extensions/localization-editor/static/assets/polyfills.meta
Normal file
12
extensions/localization-editor/static/assets/polyfills.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "43fd725b-630f-4c60-a864-7cea14073726",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e9a803d0-7f83-426e-b187-6d1caa791dc6",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "495ecfe5-9e27-4b3e-a048-df0d67da1f21",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "9ff49c15-8e75-44e3-955c-3d31f42d783d",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "3d4a4001-ed8e-4131-b245-b6b580406771",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "60bb8e28-ea3e-45ee-8314-911ce01dc8b0",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import 'intl-pluralrules';
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "c959445d-20e1-483c-8aa7-08ca07d74dd4",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1d313b84-d501-43d7-8173-4315142c25d3",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "306c90e6-641a-46df-8383-07e477f49b91",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user