八国语言+eagle图片
This commit is contained in:
1 parent
acc93d5404
commit
3bd3ba7404
46 files changed
+2520
-290
No files matched your search
@@ -0,0 +1,111 @@
|
||||
// Shared localization for the service panel and progress window.
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const LANGUAGES = ['en', 'zh_CN', 'zh_TW', 'ja_JP', 'ko_KR', 'ru_RU', 'es_ES', 'de_DE'];
|
||||
const FALLBACK = 'zh_CN';
|
||||
|
||||
function normalizeLocale(raw) {
|
||||
if (!raw) return null;
|
||||
const tag = String(raw).trim().toLowerCase().replace(/-/g, '_');
|
||||
if (tag === 'zh_tw' || tag === 'zh_hk' || tag === 'zh_hant' || tag === 'zh_mo') return 'zh_TW';
|
||||
for (const code of LANGUAGES) {
|
||||
if (code.toLowerCase() === tag) return code;
|
||||
}
|
||||
const base = tag.split('_')[0];
|
||||
if (base === 'zh') return 'zh_CN';
|
||||
for (const code of LANGUAGES) {
|
||||
if (code.toLowerCase().split('_')[0] === base) return code;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function requestedLocale() {
|
||||
try {
|
||||
const fromUrl = new URLSearchParams(location.search).get('lang');
|
||||
if (fromUrl) return fromUrl;
|
||||
} catch (error) { /* No browser location. */ }
|
||||
try {
|
||||
if (typeof eagle !== 'undefined' && eagle.app && eagle.app.locale) return eagle.app.locale;
|
||||
} catch (error) { /* Eagle API is injected asynchronously. */ }
|
||||
try {
|
||||
return navigator.language;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function pluginRoot() {
|
||||
if (window.SpinePluginPath) return window.SpinePluginPath;
|
||||
if (window.SpinePluginRoot) return window.SpinePluginRoot;
|
||||
return typeof __dirname !== 'undefined' ? __dirname : null;
|
||||
}
|
||||
|
||||
function readLocale(code) {
|
||||
try {
|
||||
const root = pluginRoot();
|
||||
if (!root) return {};
|
||||
return JSON.parse(fs.readFileSync(path.join(root, '_locales', code + '.json'), 'utf8'));
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function lookup(table, key) {
|
||||
let node = table;
|
||||
for (const part of String(key).split('.')) {
|
||||
if (!node || typeof node !== 'object') return undefined;
|
||||
node = node[part];
|
||||
}
|
||||
return typeof node === 'string' ? node : undefined;
|
||||
}
|
||||
|
||||
function apply(root) {
|
||||
const scope = root || document;
|
||||
for (const el of scope.querySelectorAll('[data-i18n]')) el.textContent = t(el.dataset.i18n);
|
||||
for (const el of scope.querySelectorAll('[data-i18n-title]')) el.title = t(el.dataset.i18nTitle);
|
||||
for (const el of scope.querySelectorAll('[data-i18n-aria-label]')) el.setAttribute('aria-label', t(el.dataset.i18nAriaLabel));
|
||||
}
|
||||
|
||||
let fallbackMessages = readLocale(FALLBACK);
|
||||
let locale = FALLBACK;
|
||||
let messages = fallbackMessages;
|
||||
|
||||
function t(key, vars) {
|
||||
let text = lookup(messages, key);
|
||||
if (text === undefined) text = lookup(fallbackMessages, key);
|
||||
if (text === undefined) return key;
|
||||
if (vars) {
|
||||
text = text.replace(/\{(\w+)\}/g, (whole, name) =>
|
||||
Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : whole);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function setLocale(raw) {
|
||||
locale = normalizeLocale(raw) || FALLBACK;
|
||||
fallbackMessages = readLocale(FALLBACK);
|
||||
messages = locale === FALLBACK ? fallbackMessages : readLocale(locale);
|
||||
document.documentElement.lang = locale.replace('_', '-');
|
||||
apply(document);
|
||||
return locale;
|
||||
}
|
||||
|
||||
const api = {
|
||||
languages: LANGUAGES,
|
||||
fallback: FALLBACK,
|
||||
get locale() { return locale; },
|
||||
normalizeLocale,
|
||||
requestedLocale,
|
||||
setLocale,
|
||||
t,
|
||||
apply,
|
||||
};
|
||||
|
||||
window.SpineThumbI18n = api;
|
||||
setLocale(requestedLocale());
|
||||
|
||||
})();
|
||||
Reference in new issue
Block a user