Bump mcschema and make changes to locales

This commit is contained in:
Misode
2020-11-05 18:42:02 +01:00
parent 8c610b99e0
commit 0b7e7c1203
6 changed files with 110 additions and 43 deletions

14
package-lock.json generated
View File

@@ -5,16 +5,16 @@
"requires": true,
"dependencies": {
"@mcschema/core": {
"version": "0.10.0-beta.6",
"resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.10.0-beta.6.tgz",
"integrity": "sha512-52QcHOBuATSL9dqI3fuNMexuJFwwF9NrtILs+IzkwAt/40e7VnR29doJW8P3JkNcZ2a9BaVtw5ExfbePj9rTFg=="
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.11.0.tgz",
"integrity": "sha512-6FZxNI2PQleT/4wDIatL7PvTZRHvbD5zWzcJLl0JgvKu7G6XXmox+TNT3L7j/auGCDSSf4wq+n+MtoXYxZ/EnQ=="
},
"@mcschema/java-1.16": {
"version": "0.5.9-beta.1",
"resolved": "https://registry.npmjs.org/@mcschema/java-1.16/-/java-1.16-0.5.9-beta.1.tgz",
"integrity": "sha512-Yh+Z6jH/GU/WgshsHfz6aRZLXGMldhaHgWfk+eWvY3f8ftrurNW+OUddCx3kwOZ4gADy5pivVhISB1yecpWKxQ==",
"version": "0.5.12",
"resolved": "https://registry.npmjs.org/@mcschema/java-1.16/-/java-1.16-0.5.12.tgz",
"integrity": "sha512-o6bnFQgilAYYMLklv3buBbVRDeK3THN2FiHHaJqHiFbs+EeNpcJ0tWm/PDRgrTUnw8TIfiNft6Ro992NwWXkkg==",
"requires": {
"@mcschema/core": "^0.10.0-beta.3"
"@mcschema/core": "^0.11.0"
}
},
"@mcschema/locales": {

View File

@@ -12,8 +12,8 @@
"author": "Misode",
"license": "MIT",
"dependencies": {
"@mcschema/core": "^0.10.0-beta.6",
"@mcschema/java-1.16": "^0.5.9-beta.1",
"@mcschema/core": "^0.11.0",
"@mcschema/java-1.16": "^0.5.12",
"@mcschema/locales": "^0.1.11",
"@types/google.analytics": "0.0.40",
"@types/split.js": "^1.4.0",

View File

@@ -1,9 +1,9 @@
import {
DataModel,
Errors,
locale,
} from '@mcschema/core'
import { AbstractView } from './AbstractView'
import { locale } from './locales'
export class ErrorsView extends AbstractView {
target: HTMLElement

View File

@@ -1,12 +1,5 @@
import Split from 'split.js'
import {
Base,
DataModel,
locale,
LOCALES,
ModelPath,
Path,
} from '@mcschema/core'
import { Base, DataModel, ModelPath, Path } from '@mcschema/core'
import { getCollections, getSchemas } from '@mcschema/java-1.16'
import { VisualizerView } from './visualization/VisualizerView'
import { RegistryFetcher } from './RegistryFetcher'
@@ -16,6 +9,7 @@ import { ErrorsView } from './ErrorsView'
import config from '../config.json'
import { BiomeNoiseVisualizer } from './visualization/BiomeNoiseVisualizer'
import { Mounter } from './Mounter'
import { getLanguage, hasLocale, locale, registerLocale, setLanguage } from './locales'
const LOCAL_STORAGE_THEME = 'theme'
const LOCAL_STORAGE_LANGUAGE = 'language'
@@ -92,9 +86,9 @@ const treeViewNodeInjector = (path: ModelPath, mounter: Mounter) => {
const fetchLocale = async (id: string) => {
const response = await fetch(publicPath + `locales/${id}.json`)
LOCALES.register(id, await response.json())
registerLocale(id, await response.json())
}
LOCALES.language = localStorage.getItem(LOCAL_STORAGE_LANGUAGE)?.toLowerCase() ?? 'en'
setLanguage(localStorage.getItem(LOCAL_STORAGE_LANGUAGE)?.toLowerCase())
const homeLink = document.getElementById('home-link')!
const homeGenerators = document.getElementById('home-generators')!
@@ -151,8 +145,8 @@ const views = {
const COLLECTIONS = getCollections()
Promise.all([
fetchLocale(LOCALES.language),
...(LOCALES.language === 'en' ? [] : [fetchLocale('en')]),
fetchLocale(getLanguage()),
...(getLanguage() === 'en' ? [] : [fetchLocale('en')]),
RegistryFetcher(COLLECTIONS, config.registries)
]).then(responses => {
@@ -182,29 +176,29 @@ Promise.all([
}
selectedModel.textContent = title
document.title = title
}
const updateLanguage = (id: string, store = false) => {
LOCALES.language = id
if (store) {
localStorage.setItem(LOCAL_STORAGE_LANGUAGE, id)
}
document.querySelectorAll('[data-i18n]').forEach(el => {
el.textContent = locale(el.attributes.getNamedItem('data-i18n')!.value)
})
}
const updateLanguage = (id: string, store = false) => {
setLanguage(id)
if (store) {
localStorage.setItem(LOCAL_STORAGE_LANGUAGE, id)
}
languageSelectorMenu.innerHTML = ''
config.languages.forEach(lang => {
languageSelectorMenu.insertAdjacentHTML('beforeend',
`<div class="btn${lang.code === LOCALES.language ? ' selected' : ''}">${lang.name}</div>`)
`<div class="btn${lang.code === getLanguage() ? ' selected' : ''}">${lang.name}</div>`)
languageSelectorMenu.lastChild?.addEventListener('click', evt => {
updateLanguage(lang.code, true)
languageSelectorMenu.style.visibility = 'hidden'
})
})
if (LOCALES.has(id)) {
if (hasLocale(id)) {
updateModel()
} else {
fetchLocale(id).then(r => {
@@ -392,7 +386,7 @@ Promise.all([
}
}
updateLanguage(LOCALES.language)
updateLanguage(getLanguage())
}
reload(location.pathname, false)
document.body.style.visibility = 'initial'

View File

@@ -1,4 +1,5 @@
import { locale, Hook, ModelPath, Path, StringHookParams, ValidationOption, EnumOption, INode, DataModel, MapNode, StringNode } from '@mcschema/core'
import { Hook, ModelPath, Path, StringHookParams, ValidationOption, EnumOption, INode, DataModel, MapNode, StringNode } from '@mcschema/core'
import { errorLocale, helpLocale, locale, pathLocale, segmentedLocale } from '../locales'
import { Mounter } from '../Mounter'
import { hexId } from '../utils'
@@ -39,12 +40,12 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
const pathWithChoiceContext = config?.choiceContext ? new Path([], [config.choiceContext]) : config?.context ? new Path([], [config.context]) : path
const inject = choices.map(c => {
if (c.type === choice.type) {
return `<button class="selected" disabled>${pathWithChoiceContext.push(c.type).locale()}</button>`
return `<button class="selected" disabled>${pathLocale(pathWithChoiceContext.push(c.type))}</button>`
}
const buttonId = mounter.registerClick(el => {
path.model.set(path, c.change ? c.change(value) : c.node.default())
})
return `<button data-id="${buttonId}">${pathWithChoiceContext.push(c.type).locale()}</button>`
return `<button data-id="${buttonId}">${pathLocale(pathWithChoiceContext.push(c.type))}</button>`
}).join('')
const [prefix, suffix, body] = choice.node.hook(this, pathWithContext, value, mounter)
@@ -67,14 +68,14 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
if (Array.isArray(value)) {
body = value.map((childValue, index) => {
const removeId = mounter.registerClick(el => path.model.set(path.push(index), undefined))
const childPath = path.push(index).localePush('entry')
const childPath = path.push(index).contextPush('entry')
const category = children.category(childPath)
const [cPrefix, cSuffix, cBody] = children.hook(this, childPath, childValue, mounter)
return `<div class="node-entry"><div class="node ${children.type(childPath)}-node" ${category ? `data-category="${category}"` : ''} ${childPath.error()} ${childPath.help()}>
return `<div class="node-entry"><div class="node ${children.type(childPath)}-node" ${category ? `data-category="${category}"` : ''} ${errorLocale(childPath)} ${helpLocale(childPath)}>
<div class="node-header">
<button class="remove" data-id="${removeId}"></button>
${cPrefix}
<label>${path.localePush('entry').locale([`${index}`])}</label>
<label>${pathLocale(path.contextPush('entry'), [`${index}`])}</label>
${cSuffix}
</div>
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
@@ -109,7 +110,7 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
const childPath = path.modelPush(key)
const category = children.category(childPath)
const [cPrefix, cSuffix, cBody] = children.hook(this, childPath, value[key], mounter)
return `<div class="node-entry"><div class="node ${children.type(childPath)}-node" ${category ? `data-category="${category}"` : ''} ${childPath.error()} ${childPath.help()}>
return `<div class="node-entry"><div class="node ${children.type(childPath)}-node" ${category ? `data-category="${category}"` : ''} ${errorLocale(childPath)} ${helpLocale(childPath)}>
<div class="node-header">
<button class="remove" data-id="${removeId}"></button>
${cPrefix}
@@ -159,10 +160,10 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
const childPath = getChildModelPath(path, k)
const category = field.category(childPath)
const [cPrefix, cSuffix, cBody] = field.hook(this, childPath, value[k], mounter)
return `<div class="node ${field.type(childPath)}-node" ${category ? `data-category="${category}"` : ''} ${childPath.error()} ${childPath.help()}>
return `<div class="node ${field.type(childPath)}-node" ${category ? `data-category="${category}"` : ''} ${errorLocale(childPath)} ${helpLocale(childPath)}>
<div class="node-header">
${cPrefix}
<label>${childPath.locale()}</label>
<label>${pathLocale(childPath)}</label>
${cSuffix}
</div>
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
@@ -207,7 +208,7 @@ function rawString({ node, getValues, config }: { node: INode } & StringHookPara
&& typeof config.params.pool === 'string'
&& values.length > 0) {
const contextPath = new Path(path.getArray(), [config.params.pool])
if (contextPath.localePush(values[0]).strictLocale()) {
if (segmentedLocale(contextPath.contextPush(values[0]).getContext())) {
return selectRaw(node, contextPath, values, inputId)
}
}
@@ -225,7 +226,7 @@ function selectRaw(node: INode, contextPath: Path, values: string[], inputId?: s
return `<select data-id="${inputId}">
${node.optional() ? `<option value="">${locale('unset')}</option>` : ''}
${values.map(v =>
`<option value="${v}">${contextPath.localePush(v).locale()}</option>`
`<option value="${v}">${pathLocale(contextPath.contextPush(v))}</option>`
).join('')}
</select>`
}

72
src/app/locales.ts Normal file
View File

@@ -0,0 +1,72 @@
import { ModelPath, Path } from '@mcschema/core'
interface Locale {
[key: string]: string
}
const Locales: {
[key: string]: Locale
} = {}
let language = 'en'
export function registerLocale(code: string, locale: Locale) {
Locales[code] = locale
}
export function hasLocale(code: string) {
return Locales[code] !== undefined
}
export function setLanguage(code: string | undefined) {
language = code ?? language
}
export function getLanguage() {
return language
}
export function resolveLocaleParams(value: string, params?: string[]): string | undefined {
return value?.replace(/%\d+%/g, match => {
const index = parseInt(match.slice(1, -1))
return params?.[index] !== undefined ? params[index] : match
})
}
export function locale(key: string, params?: string[]): string {
const value: string | undefined = Locales[language][key] ?? Locales.en[key]
return resolveLocaleParams(value, params) ?? key
}
export function segmentedLocale(segments: string[], params?: string[], depth = 5, minDepth = 1): string | undefined {
return [language, 'en'].reduce((prev: string | undefined, code) => {
if (prev !== undefined) return prev
const array = segments.slice(-depth);
while (array.length >= minDepth) {
const locale = resolveLocaleParams(Locales[code][array.join('.')], params)
if (locale !== undefined) return locale
array.shift()
}
return undefined
}, undefined)
}
export function pathLocale(path: Path, params?: string[]): string {
// return path.getContext().slice(-5).join('.')
return segmentedLocale(path.getContext(), params)
?? path.getContext()[path.getContext().length - 1] ?? ''
}
export function errorLocale(p: ModelPath, exact = true): string {
const errors = p.model.errors.get(p, exact)
if (errors.length === 0) return ''
return `data-error="${locale(errors[0].error, errors[0].params)}"`
}
export function helpLocale(path: ModelPath): string {
const res = segmentedLocale(path.contextPush('help').getContext(), [], 6)
if (res === undefined) return ''
return `data-help="${res}"`
}