Last active
June 28, 2023 05:18
-
-
Save mntone/e4cec10755e8f291d5663ff78ebb2b4d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"required": "Please enter a ${'fieldName'}.", | |
"minimum": { | |
"one":"${'fieldName'} must be at least one character.", | |
"other":"${'fieldName'} must be at least ${'value'} characters." | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (C) 2023 mntone | |
// This source code is licensed under the MIT license. | |
// [Example] | |
// import { Localize } from './Localize' | |
// | |
// const message = Localize.required({ | |
// fieldName: this.#fieldName, | |
// }) | |
// | |
// const messageWithNumber = Localize.minimum(minLength, { | |
// fieldName: this.#fieldName, | |
// }) | |
// eslint-disable-next-line prefer-named-capture-group | |
const variableRe = /\${'([a-zA-Z]\w*)'}/g | |
const _localize = (strings, keys) => { | |
return values => { | |
const result = [strings[0]] | |
keys.forEach((key, i) => { | |
result.push(values[key], strings[i + 1]) | |
}) | |
return result.join('') | |
} | |
} | |
const _localizeOneOther = (one, other) => { | |
return (value, values) => { | |
values.value = value | |
if (value === 1) { | |
return one(values) | |
} else { | |
return other(values) | |
} | |
} | |
} | |
const _localizeOther = other => { | |
return (value, values) => { | |
values.value = value | |
return other(values) | |
} | |
} | |
/** | |
* @param {object|string} d | |
* @returns {object|string} | |
*/ | |
const _parseLocaleData = d => { | |
let ret | |
if (typeof d === 'object') { | |
ret = Object.create(null) | |
if (typeof d.other === 'string') { | |
if (typeof d.one === 'string') { | |
ret = _localizeOneOther(_parseLocaleData(d.one), _parseLocaleData(d.other)) | |
} else { | |
ret = _localizeOther(_parseLocaleData(d.other)) | |
} | |
} else { | |
for (const [key, value] of Object.entries(d)) { | |
ret[key] = _parseLocaleData(value) | |
} | |
} | |
} else { | |
const strings = [] | |
const keys = [] | |
let p = 0 | |
let result = null | |
while ((result = variableRe.exec(d)) !== null) { | |
const variableName = result[1] | |
strings.push(d.substring(p, result.index)) | |
keys.push(variableName) // ${'[here]'} | |
p = variableRe.lastIndex | |
} | |
if (p !== 0) { | |
if (p !== d.length) { | |
strings.push(d.substring(p)) | |
} | |
ret = _localize(Object.freeze(strings), Object.freeze(keys)) | |
} else { | |
ret = d | |
} | |
} | |
return ret | |
} | |
const languages = ['ja'] | |
const fallbackLanguage = 'en' | |
const Localize = Object.create(null) | |
Localize.loaded = false | |
const _load = language => { | |
fetch(`/a/${language}.locale.json`, { | |
referrer: '', | |
mode: 'same-origin', | |
}).then(r => r.json()).then(d => { | |
Object.assign(Localize, _parseLocaleData(d)) | |
Localize.loaded = true | |
Object.freeze(Localize) | |
}) | |
} | |
Localize.init = () => { | |
for (const language of languages) { | |
if (new RegExp(`^${language}(?:\b|$)`).test(navigator.language)) { | |
_load(language) | |
return | |
} | |
} | |
_load(fallbackLanguage) | |
} | |
export { | |
Localize, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment