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:
@@ -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": {}
|
||||
}
|
||||
Reference in New Issue
Block a user