@@ -45,10 +45,16 @@ export type TransformFnProps<TTrKey extends string = string> = {
4545 trArgs : ( Stringifiable | Record < string , Stringifiable > ) [ ] ;
4646} ;
4747
48- /** Function that transforms a matched translation string into something else */
48+ /** Function that transforms a matched translation string into another string */
4949export type TransformFn < TTrKey extends string = string > = ( props : TransformFnProps < TTrKey > ) => Stringifiable ;
5050
51- /** Pass a translation object to this function to get all keys in the object */
51+ /**
52+ * Pass a recursive or flat translation object to this generic type to get all keys in the object.
53+ * @example ```ts
54+ * type Keys = TrKeys<{ a: { b: "foo" }, c: "bar" }>;
55+ * // result: type Keys = "a.b" | "c"
56+ * ```
57+ */
5258export type TrKeys < TTrObj , P extends string = "" > = {
5359 [ K in keyof TTrObj ] : K extends string | number | boolean | null | undefined
5460 ? TTrObj [ K ] extends object
@@ -323,7 +329,6 @@ export { tr };
323329
324330/** All translation keys from the file `@assets/translations/en-US.json` */
325331export type TrKeyEn = TrKeys < typeof trEn > | "_" ;
326- // export type TrKeyEn = TrKeys<typeof trEn> | (string & {});
327332
328333/** The default and fallback locale */
329334export const defaultLocale = "en-US" ;
@@ -334,12 +339,16 @@ const transforms = [
334339 [
335340 / \$ \{ ( [ a - z A - Z 0 - 9 $ _ - ] + ) \} / gm,
336341 ( { matches, trArgs, trValue } ) => {
342+ const patternStart = "${" ,
343+ patternEnd = "}" ,
344+ patternRegex = / \$ \{ .+ \} / m;
345+
337346 let str = String ( trValue ) ;
338347
339- const eachKeyInTrString = ( keys : string [ ] ) => keys . every ( ( key ) => trValue . includes ( "${" + key + "}" ) ) ;
348+ const eachKeyInTrString = ( keys : string [ ] ) => keys . every ( ( key ) => trValue . includes ( ` ${ patternStart } ${ key } ${ patternEnd } ` ) ) ;
340349
341350 const namedMapping = ( ) => {
342- if ( ! str . includes ( "${" ) || typeof trArgs [ 0 ] === "undefined" || typeof trArgs [ 0 ] !== "object" || ! eachKeyInTrString ( Object . keys ( trArgs [ 0 ] ?? { } ) ) )
351+ if ( ! str . includes ( patternStart ) || typeof trArgs [ 0 ] === "undefined" || typeof trArgs [ 0 ] !== "object" || ! eachKeyInTrString ( Object . keys ( trArgs [ 0 ] ?? { } ) ) )
343352 return ;
344353 for ( const match of matches ) {
345354 const repl = ( trArgs [ 0 ] as Record < string , string > ) [ match [ 1 ] ] ;
@@ -349,7 +358,7 @@ const transforms = [
349358 } ;
350359
351360 const positionalMapping = ( ) => {
352- if ( ! ( / \$ \{ . + \} / m . test ( str ) ) || ! trArgs [ 0 ] )
361+ if ( ! ( patternRegex . test ( str ) ) || ! trArgs [ 0 ] )
353362 return ;
354363 let matchNum = - 1 ;
355364 for ( const match of matches ) {
@@ -359,7 +368,10 @@ const transforms = [
359368 }
360369 } ;
361370
362- if ( trArgs [ 0 ] && typeof trArgs [ 0 ] === "object" && trArgs [ 0 ] !== null && eachKeyInTrString ( Object . keys ( trArgs [ 0 ] ?? { } ) ) && String ( trArgs [ 0 ] ) . startsWith ( "[object" ) )
371+ /** Whether the first args parameter is an object that doesn't implement a custom `toString` method */
372+ const isArgsObject = trArgs [ 0 ] && typeof trArgs [ 0 ] === "object" && trArgs [ 0 ] !== null && String ( trArgs [ 0 ] ) . startsWith ( "[object" ) ;
373+
374+ if ( isArgsObject && eachKeyInTrString ( Object . keys ( trArgs [ 0 ] ! ) ) )
363375 namedMapping ( ) ;
364376 else
365377 positionalMapping ( ) ;
@@ -401,7 +413,7 @@ export async function initTranslations(): Promise<void> {
401413
402414//#region getLocMap
403415
404- /** Returns the localization map for all locales, given the common translation key */
416+ /** Returns a localization map for all locales where the given common translation key exists */
405417export function getLocMap ( trKey : TrKeyEn , prefix = "" ) : LocalizationMap {
406418 const locMap = { } as LocalizationMap ;
407419
@@ -444,12 +456,12 @@ export function getLocMap(trKey: TrKeyEn, prefix = ""): LocalizationMap {
444456 value = value ?. [ part ] ;
445457 }
446458 if ( typeof value === "string" )
447- locMap [ language as keyof LocalizationMap ] = prefix + transform ( value ) ;
459+ locMap [ language as keyof LocalizationMap ] = ` ${ prefix } ${ transform ( value ) } ` ;
448460
449461 // try falling back to `trObj["key.parts"]`
450462 value = trObj ?. [ trKey ] ;
451463 if ( typeof value === "string" )
452- locMap [ language as keyof LocalizationMap ] = prefix + transform ( value ) ;
464+ locMap [ language as keyof LocalizationMap ] = ` ${ prefix } ${ transform ( value ) } ` ;
453465 }
454466
455467 return Object . keys ( locMap ) . length === 0
0 commit comments