mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-10-20 05:15:31 +00:00
refactor(desktop): share one active→default→key i18n resolver
Collapse the fallback walk out of `translateNow` into a single `translateFrom` that takes a per-locale message source, so any translator (core catalog or a plugin's bundles) reuses the exact dot-path walk, interpolation, and active-locale/English/raw-key chain. Adds `getRuntimeI18nLocale`.
This commit is contained in:
parent
7db2decbea
commit
228655a73a
1 changed files with 31 additions and 18 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { TRANSLATIONS } from './catalog'
|
||||
import { DEFAULT_LOCALE } from './languages'
|
||||
import type { Locale, Translations } from './types'
|
||||
import type { Locale } from './types'
|
||||
|
||||
let runtimeLocale: Locale = DEFAULT_LOCALE
|
||||
|
||||
|
|
@ -8,17 +8,13 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|||
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
||||
}
|
||||
|
||||
function resolvePath(catalog: Translations, key: string): unknown {
|
||||
return key.split('.').reduce<unknown>((current, part) => {
|
||||
if (!isRecord(current)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return current[part]
|
||||
}, catalog)
|
||||
/** Walk a dot-path (`a.b.c`) into a nested message tree. */
|
||||
function resolvePath(source: unknown, key: string): unknown {
|
||||
return key.split('.').reduce<unknown>((current, part) => (isRecord(current) ? current[part] : undefined), source)
|
||||
}
|
||||
|
||||
function renderTranslation(value: unknown, args: unknown[]): string | null {
|
||||
/** A string is returned as-is, a function is called with `args`, else `null`. */
|
||||
function render(value: unknown, args: unknown[]): null | string {
|
||||
if (typeof value === 'string') {
|
||||
return value
|
||||
}
|
||||
|
|
@ -30,19 +26,22 @@ function renderTranslation(value: unknown, args: unknown[]): string | null {
|
|||
return null
|
||||
}
|
||||
|
||||
export function setRuntimeI18nLocale(locale: Locale) {
|
||||
runtimeLocale = locale
|
||||
}
|
||||
|
||||
export function translateNow(key: string, ...args: unknown[]): string {
|
||||
const active = renderTranslation(resolvePath(TRANSLATIONS[runtimeLocale], key), args)
|
||||
/** The active → DEFAULT → key resolution every translator shares. `source`
|
||||
* yields a message tree per locale — the app catalog, or a plugin's bundles. */
|
||||
export function translateFrom(
|
||||
source: (locale: Locale) => unknown,
|
||||
locale: Locale,
|
||||
key: string,
|
||||
args: unknown[]
|
||||
): string {
|
||||
const active = render(resolvePath(source(locale), key), args)
|
||||
|
||||
if (active !== null) {
|
||||
return active
|
||||
}
|
||||
|
||||
if (runtimeLocale !== DEFAULT_LOCALE) {
|
||||
const fallback = renderTranslation(resolvePath(TRANSLATIONS[DEFAULT_LOCALE], key), args)
|
||||
if (locale !== DEFAULT_LOCALE) {
|
||||
const fallback = render(resolvePath(source(DEFAULT_LOCALE), key), args)
|
||||
|
||||
if (fallback !== null) {
|
||||
return fallback
|
||||
|
|
@ -51,3 +50,17 @@ export function translateNow(key: string, ...args: unknown[]): string {
|
|||
|
||||
return key
|
||||
}
|
||||
|
||||
export function setRuntimeI18nLocale(locale: Locale) {
|
||||
runtimeLocale = locale
|
||||
}
|
||||
|
||||
/** The locale module-level translators resolve against (the app's active
|
||||
* `display.language`). Plugin `ctx.i18n.t` reads this too. */
|
||||
export function getRuntimeI18nLocale(): Locale {
|
||||
return runtimeLocale
|
||||
}
|
||||
|
||||
export function translateNow(key: string, ...args: unknown[]): string {
|
||||
return translateFrom(locale => TRANSLATIONS[locale], runtimeLocale, key, args)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue