shithub: scrax

ref: 81d1e4e01d7001e6a0107792e6167136787295d6
dir: /translation.js/

View raw version
import messages1 from "scratch-l10n/locales/blocks-msgs.js"
import messages2 from "scratch-l10n/locales/editor-msgs.js"
import {isRtl} from "scratch-l10n/src/supported-locales.js"

export let locale

for (let name of navigator.languages) {
	if (locale) break
	name = name.toLowerCase()
	for (let name1 in messages1) {
		if (locale) break
		let parts = name1.split("-")
		while (parts.length > 0) {
			if (parts.join("-") === name) {
				locale = name1
				break
			}
			parts.pop()
		}
	}
}

locale ??= "en"
document.documentElement.lang = locale
if (isRtl(locale)) document.dir = "rtl"
else document.dir = "ltr"

let messages = {...messages1[locale], ...messages2[locale]}
let messages0 = [...Object.entries(messages1.en), ...Object.entries(messages2.en)]

export function getName(stage, type, ...args)
{
	if (locale === "en") return
	if (type.shape === "slot" && type.dynamic) return
	if (type.category === "custom" && !type.hat) return
	
	let symbol = Symbol()
	
	let name0 = args
	if (type.shape !== "slot") {
		args = args.map(arg => ({[symbol]: arg}))
		name0 = stage.scratch.getName(type, ...args) ?? type.name?.(...args)
		if (!name0) return
	}
	
	let category = type.category ?? "extensions"
	if (type.category === "events") category = "event"
	if (type.category === "variables") category = "data"
	if (type.category === "lists") category = "data"
	
	name0 = name0.map(part =>
	{
		if (typeof part === "string") return part
		if (part instanceof Node) return part
		if (part[symbol]) return part
		if (!part.options) return part
		let options = part.options.map(option =>
		{
			let label = option.label
			
			for (let [key, name] of messages0) {
				if (!["extensions", "custom"].includes(category)) {
					if (!key.startsWith(category.toUpperCase() + "_")) continue
				}
				if (name === label) {
					label = messages[key]
					break
				}
			}
			
			return {...option, label}
		})
		
		return {...part, options}
	})
	
	let icon
	if (name0[0] instanceof Element && name0[0].querySelector("svg")) icon = name0.shift()
	
	let regex = new RegExp("^" + name0.map((n, i) => typeof n !== "string" ? `(?<i${i}>%[0-9]+|\\[[a-zA-Z_]+\\]+)`: RegExp.escape(n)).join("\\s*") + "$", "u")
	
	for (let [key, name] of messages0) {
		
		if (!["extensions", "custom"].includes(category)) {
			if (!key.startsWith(category.toUpperCase() + "_")) continue
		}
		
		if (key === "CONTROL_STOP" && !name.includes("%1")) name += " %1"
		let match = name.match(regex)
		if (!match) continue
		
		let message = messages[key]
		if (key === "CONTROL_STOP" && !message.includes("%1")) message += " %1"
		let parts = message.split(/(%[0-9]+|\[[a-zA-Z_]+\]+)/g)
		
		return [...icon ? [icon] : [], ...parts.map(part =>
		{
			if (!part.match(/^%[0-9]+|\[[a-zA-Z_]+\]+$/)) return part.replace(/\s+/, " ").trim()
			for (let [i, part1] of Object.entries(match.groups)) {
				if (part === part1) {
					let part2 = name0[i.slice(1)]
					return part2[symbol] ?? part2
				}
			}
		})]
	}
}

export function getMessage(name, fn = m => m)
{
	let message = messages[name] ?? messages1.en[name] ?? messages2.en[name]
	if (message) return fn(message)
}