@senspark/ee
Version:
utility library for cocos creator
172 lines (153 loc) • 5.52 kB
text/typescript
import assert = require('assert');
import * as Polyglot from 'node-polyglot';
import { ObserverManager } from './ObserverManager';
import { ProfileManager } from './ProfileManager';
type Observer = () => void;
export class LanguageManager extends ObserverManager<Observer> {
private static sharedInstance?: LanguageManager;
/** Gets the singleton. */
public static getInstance(): LanguageManager {
return this.sharedInstance || (this.sharedInstance = new this());
}
/**
* Current config directory.
* Actually UUID in editor mode and relative path in release mode.
*/
private configDir?: string;
/** Current active language. */
private currentLanguage?: string;
private configs: { [index: string]: { [key: string]: string | undefined } | undefined };
/** Wrappee i18n manager. */
private polyglot: Polyglot;
private constructor() {
super();
// Hide construction.
this.configs = {};
this.polyglot = new Polyglot();
const profile = ProfileManager.getInstance();
this.currentLanguage = profile.loadData('current_language');
this.configDir = profile.loadData('config_dir');
this.updateConfigs();
}
/**
* Gets all available languages.
* @return Array of language names.
*/
public getLanguages(): string[] {
return Object.keys(this.configs);
}
/**
* Gets the config dir.
* Used in editor only.
*/
public getConfigDir(): string | undefined {
return this.configDir;
}
/**
* Sets the config directory.
* @param path The directory path.
*/
public setConfigDir(path: string): void {
this.configDir = path;
if (CC_EDITOR) {
const profile = ProfileManager.getInstance();
profile.saveData('config_dir', this.configDir);
}
this.updateConfigs();
this.updateLanguage();
}
/** Clears the language directory. */
public resetConfigDir(): void {
this.configDir = undefined;
if (CC_EDITOR) {
const profile = ProfileManager.getInstance();
profile.saveData('config_dir', this.configDir);
}
this.updateConfigs();
}
private updateConfigs(): void {
this.configs = {};
if (this.configDir === undefined) {
this.updateLanguage();
return;
}
if (CC_EDITOR) {
Editor.assetdb.queryUrlByUuid(this.configDir, (err, url) => {
const pattern = url + '/*.json';
const type = (cc.ENGINE_VERSION >= '2' ? 'json' : 'text');
Editor.assetdb.queryAssets(pattern, type, (err2, result) => {
result.forEach((item: any) => {
import(item.path).then(config => {
const language = this.parseLanguage(item.path);
this.configs[language] = config;
this.updateLanguage();
});
});
});
});
} else {
cc.loader.loadResDir(this.configDir, (err: any, results: any[], urls: string[]) => {
for (let i = 0; i < urls.length; ++i) {
const path = urls[i] + '.json'; // Suffixed with .json for regex matching.
const content = results[i];
const language = this.parseLanguage(path);
if (cc.ENGINE_VERSION >= '2') {
this.configs[language] = content.json;
} else {
this.configs[language] = content;
}
this.updateLanguage();
}
});
}
}
private updateLanguage(): void {
this.polyglot.clear();
if (this.currentLanguage !== undefined) {
const config = this.configs[this.currentLanguage];
if (config !== undefined) {
this.polyglot.extend(config);
}
}
this.dispatch(observer => observer());
}
/** Gets the active language. */
public getCurrentLanguage(): string | undefined {
return this.currentLanguage;
}
/** Sets the active language. */
public setCurrentLanguage(language: string | undefined): void {
this.currentLanguage = language;
if (CC_EDITOR) {
const profile = ProfileManager.getInstance();
profile.saveData('current_language', language);
}
this.updateLanguage();
}
/** Gets the language format in the current language. */
public getFormat(key: string): string | undefined {
if (this.currentLanguage === undefined) {
return undefined;
}
const config = this.configs[this.currentLanguage];
if (config === undefined) {
return undefined;
}
return config[key];
}
public parseFormat(key: string, options?: Polyglot.InterpolationOptions): string | undefined {
if (this.polyglot.has(key)) {
return this.polyglot.t(key, options!);
}
return undefined;
}
/** Detects language for the config path. */
private parseLanguage(path: string): string {
const regex = /\/(\w+)\.\w+$/g;
const match = regex.exec(path);
if (match === null) {
return '';
}
return match[1];
}
}