Skip to content

Instantly share code, notes, and snippets.

@mntone
Last active June 28, 2023 05:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mntone/e4cec10755e8f291d5663ff78ebb2b4d to your computer and use it in GitHub Desktop.
Save mntone/e4cec10755e8f291d5663ff78ebb2b4d to your computer and use it in GitHub Desktop.
{
"required": "Please enter a ${'fieldName'}.",
"minimum": {
"one":"${'fieldName'} must be at least one character.",
"other":"${'fieldName'} must be at least ${'value'} 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