intor-translator 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,8 +17,6 @@ Easy to use, modular at its core, and fully extensible.
17
17
 
18
18
  </div>
19
19
 
20
- > Structured 󠁯•󠁏 Predictable 󠁯•󠁏 Beautifully simple
21
-
22
20
  ## Features
23
21
 
24
22
  - 🔧 **Modular Pipeline** – A pluggable, hook-driven flow for any translation logic.
package/dist/index.cjs CHANGED
@@ -121,7 +121,7 @@ var loading = rura.rura.createHook(
121
121
  };
122
122
  }
123
123
  const { loadingMessage } = config;
124
- if ("loadingMessage" in config) {
124
+ if (loadingMessage !== void 0) {
125
125
  return { early: true, output: loadingMessage };
126
126
  }
127
127
  },
@@ -140,7 +140,7 @@ var missing = rura.rura.createHook(
140
140
  };
141
141
  }
142
142
  const { missingMessage } = config;
143
- if ("missingMessage" in config) {
143
+ if (missingMessage !== void 0) {
144
144
  return { early: true, output: missingMessage };
145
145
  }
146
146
  return { early: true, output: key };
@@ -176,6 +176,7 @@ var DEFAULT_HOOKS = [
176
176
  format,
177
177
  interpolate
178
178
  ];
179
+ rura.rura.createPipeline(DEFAULT_HOOKS).debugHooks();
179
180
 
180
181
  // src/translators/base-translator/base-translator.ts
181
182
  var BaseTranslator = class {
@@ -250,12 +251,18 @@ function runTranslate(options) {
250
251
  function translate(options) {
251
252
  const { early, ctx, output } = runTranslate(options);
252
253
  if (early === true) return output;
254
+ if (ctx.finalMessage === void 0) {
255
+ throw new Error("Invariant violated: missing hook did not produce output");
256
+ }
253
257
  return ctx.finalMessage;
254
258
  }
255
259
 
256
260
  // src/translators/methods/translate-raw.ts
257
261
  function translateRaw(options) {
258
262
  const { ctx } = runTranslate(options);
263
+ if (ctx.rawValue === void 0) {
264
+ throw new Error("Invariant violated: missing hook did not produce output");
265
+ }
259
266
  return ctx.rawValue;
260
267
  }
261
268
 
@@ -340,7 +347,7 @@ var ScopeTranslator = class extends CoreTranslator {
340
347
  constructor(options) {
341
348
  super(options);
342
349
  }
343
- /** Create a scoped translator with a prefix key, providing `t` and `hasKey` for nested keys. */
350
+ /** Create a scoped translator with a prefix key for resolving nested message paths. */
344
351
  scoped(preKey) {
345
352
  return {
346
353
  hasKey: (key, targetLocale) => {
@@ -363,6 +370,18 @@ var ScopeTranslator = class extends CoreTranslator {
363
370
  key: fullKey,
364
371
  replacements
365
372
  });
373
+ },
374
+ tRaw: (key, replacements) => {
375
+ const fullKey = getFullKey(preKey, key);
376
+ return translateRaw({
377
+ hooks: this.hooks,
378
+ messages: this._messages,
379
+ locale: this._locale,
380
+ isLoading: this._isLoading,
381
+ translateConfig: this.translateConfig,
382
+ key: fullKey,
383
+ replacements
384
+ });
366
385
  }
367
386
  };
368
387
  }
package/dist/index.d.cts CHANGED
@@ -154,6 +154,16 @@ type NodeKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never
154
154
  type LeafKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never : M extends object ? {
155
155
  [K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}.${LeafKeys<M[K], Prev[D]>}` : never;
156
156
  }[keyof M] : never;
157
+ /**
158
+ * Resolves the value type at a given dot-separated leaf key
159
+ * within a nested message object.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * LeafValue<{ a: { b: { c: string } } }, "a.b.c"> // → string
164
+ * ```
165
+ */
166
+ type LeafValue<M, K extends string> = K extends `${infer Seg}.${infer Rest}` ? Seg extends keyof M ? LeafValue<M[Seg], Rest> : never : K extends keyof M ? M[K] : never;
157
167
 
158
168
  /**
159
169
  * Extracts all **node keys** from the messages
@@ -201,6 +211,13 @@ type LocalizedNodeKeys<M = unknown, L extends keyof M | "union" = "union", D ext
201
211
  * ```
202
212
  */
203
213
  type LocalizedLeafKeys<M = unknown, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? L extends "union" ? LeafKeys<M[keyof M], D> : LeafKeys<M[Extract<L, keyof M>], D> : string;
214
+ /**
215
+ * Resolves the value type of a **localized leaf key**
216
+ * from the messages of a specified locale (or union of locales).
217
+ *
218
+ * - Fallback to `MessageValue` if M is not LocaleMessages
219
+ */
220
+ type LocalizedLeafValue<M = unknown, K extends string = string, L extends keyof M | "union" = "union"> = M extends LocaleMessages ? L extends "union" ? LeafValue<M[keyof M], K> : LeafValue<M[Extract<L, keyof M>], K> : MessageValue;
204
221
 
205
222
  /**
206
223
  * Resolves the type at a dot-separated key in a nested object.
@@ -236,6 +253,21 @@ type MessagesAtPreKey<T, PK extends string> = PK extends `${infer Head}.${infer
236
253
  * ```
237
254
  */
238
255
  type ScopedLeafKeys<M, PK extends string, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer Messages ? Messages extends MessageValue ? MessagesAtPreKey<Messages, PK> extends infer Scoped ? Scoped extends MessageObject ? LeafKeys<Scoped, D> : never : never : never : never : string;
256
+ /**
257
+ * Resolves the value type of a scoped leaf key (`K`)
258
+ * under a prefix path (`PK`) from localized messages.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * const messages = {
263
+ * en: { a: { b: { c: "hello" }, z: [123] } },
264
+ * };
265
+ *
266
+ * ScopedLeafValue<typeof messages, "a", "z">; // number[]
267
+ * ScopedLeafValue<typeof messages, "a.b", "c">; // string
268
+ * ```
269
+ */
270
+ type ScopedLeafValue<M, PK extends string, K extends string, L extends keyof M | "union" = "union"> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer Messages ? Messages extends MessageValue ? MessagesAtPreKey<Messages, PK> extends infer Scoped ? Scoped extends MessageObject ? LeafValue<Scoped, K> : never : never : never : never : MessageValue;
239
271
 
240
272
  /**
241
273
  * Configuration options for translation behavior.
@@ -262,13 +294,13 @@ type TranslateHandlers = {
262
294
  formatHandler?: FormatHandler;
263
295
  };
264
296
  /** Function called when translation is still loading. */
265
- type LoadingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
297
+ type LoadingHandler = (ctx: HandlerContext) => MessageValue;
266
298
  /** Function called when no message is found for the given key. */
267
- type MissingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
299
+ type MissingHandler = (ctx: HandlerContext) => MessageValue;
268
300
  /** Function to format a resolved message. */
269
- type FormatHandler<Result = unknown> = (ctx: HandlerContext & {
301
+ type FormatHandler = (ctx: HandlerContext & {
270
302
  rawString: string;
271
- }) => Result;
303
+ }) => MessageValue;
272
304
  /**
273
305
  * Snapshot of the translate pipeline context exposed to handlers.
274
306
  *
@@ -281,10 +313,8 @@ type HandlerContext = Readonly<Omit<TranslateContext, "finalMessage">>;
281
313
 
282
314
  /**
283
315
  * Context object shared across the translate pipeline.
284
- *
285
- * @template Result - Final translated value type.
286
316
  */
287
- interface TranslateContext<Result = unknown> {
317
+ interface TranslateContext {
288
318
  /** Configuration for the translate pipeline. */
289
319
  config: TranslateConfig;
290
320
  /** Current messages for translation */
@@ -304,16 +334,16 @@ interface TranslateContext<Result = unknown> {
304
334
  /** Raw string message before formatting. */
305
335
  rawString?: string;
306
336
  /** Message after formatting (e.g. ICU, custom formatters) */
307
- formattedMessage?: unknown;
337
+ formattedMessage?: MessageValue;
308
338
  /** Final value produced by the pipeline */
309
- finalMessage?: Result;
339
+ finalMessage?: MessageValue;
310
340
  /** Free-form metadata shared between hooks. */
311
341
  meta: Record<string, unknown>;
312
342
  }
313
343
  /**
314
344
  * A single step in the translate pipeline.
315
345
  */
316
- type TranslateHook = RuraHook<TranslateContext>;
346
+ type TranslateHook = RuraHook<TranslateContext, MessageValue>;
317
347
 
318
348
  /**
319
349
  * Options for initializing a translator
@@ -406,21 +436,22 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, L ext
406
436
  /** Check if a key exists in the specified locale or current locale. */
407
437
  hasKey: <K extends LocalizedLeafKeys<M, L>>(key: K, targetLocale?: Locale<M>) => boolean;
408
438
  /** Get the translated message for a key, with optional replacements. */
409
- t: <Result = string, K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => Result;
439
+ t: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => LocalizedLeafValue<M, K, L>;
410
440
  /** Get the raw message value for a key without formatting or interpolation. */
411
- tRaw: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => MessageValue | undefined;
441
+ tRaw: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => LocalizedLeafValue<M, K, L>;
412
442
  }
413
443
 
414
444
  type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
415
- type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, L extends keyof M | "union" = "union", K = LocalizedLeafKeys<M, L>> = {
445
+ type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, L extends keyof M | "union" = "union", PK extends string | undefined = undefined, K extends string = PK extends string ? ScopedLeafKeys<M, PK, L> : LocalizedLeafKeys<M, L>> = {
416
446
  hasKey: (key?: K, targetLocale?: Locale<M>) => boolean;
417
- t: <Result = string>(key?: K, replacements?: Replacement) => Result;
447
+ t: <Key extends K>(key?: Key, replacements?: Replacement) => PK extends string ? ScopedLeafValue<M, PK, Key, L> : LocalizedLeafValue<M, Key, L>;
448
+ tRaw: <Key extends K>(key?: Key, replacements?: Replacement) => PK extends string ? ScopedLeafValue<M, PK, Key, L> : LocalizedLeafValue<M, Key, L>;
418
449
  };
419
450
 
420
451
  declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown, L extends keyof M | "union" = "union"> extends CoreTranslator<M> {
421
452
  constructor(options: ScopeTranslatorOptions<M>);
422
- /** Create a scoped translator with a prefix key, providing `t` and `hasKey` for nested keys. */
423
- scoped<PK extends LocalizedNodeKeys<M, L> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, L, ScopedLeafKeys<M, PK, L>> : ScopeTranslatorMethods<M, L>;
453
+ /** Create a scoped translator with a prefix key for resolving nested message paths. */
454
+ scoped<PK extends LocalizedNodeKeys<M, L> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, L, PK> : ScopeTranslatorMethods<M, L>;
424
455
  }
425
456
 
426
457
  /** Semantic tag attributes map. */
@@ -489,4 +520,4 @@ interface Renderer<Output> {
489
520
  */
490
521
  declare function renderRichMessage<Output>(message: string, renderer: Renderer<Output>): Output[];
491
522
 
492
- export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedMessagesUnion, type LocalizedNodeKeys, type MessageObject, type MessageValue, type MissingHandler, type NodeKeys, type Renderer, type Replacement, type ScopedLeafKeys, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, parseRichMessage, renderRichMessage };
523
+ export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LeafValue, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedLeafValue, type LocalizedMessagesUnion, type LocalizedNodeKeys, type MessageObject, type MessageValue, type MissingHandler, type NodeKeys, type Renderer, type Replacement, type ScopedLeafKeys, type ScopedLeafValue, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, parseRichMessage, renderRichMessage };
package/dist/index.d.ts CHANGED
@@ -154,6 +154,16 @@ type NodeKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never
154
154
  type LeafKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never : M extends object ? {
155
155
  [K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}.${LeafKeys<M[K], Prev[D]>}` : never;
156
156
  }[keyof M] : never;
157
+ /**
158
+ * Resolves the value type at a given dot-separated leaf key
159
+ * within a nested message object.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * LeafValue<{ a: { b: { c: string } } }, "a.b.c"> // → string
164
+ * ```
165
+ */
166
+ type LeafValue<M, K extends string> = K extends `${infer Seg}.${infer Rest}` ? Seg extends keyof M ? LeafValue<M[Seg], Rest> : never : K extends keyof M ? M[K] : never;
157
167
 
158
168
  /**
159
169
  * Extracts all **node keys** from the messages
@@ -201,6 +211,13 @@ type LocalizedNodeKeys<M = unknown, L extends keyof M | "union" = "union", D ext
201
211
  * ```
202
212
  */
203
213
  type LocalizedLeafKeys<M = unknown, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? L extends "union" ? LeafKeys<M[keyof M], D> : LeafKeys<M[Extract<L, keyof M>], D> : string;
214
+ /**
215
+ * Resolves the value type of a **localized leaf key**
216
+ * from the messages of a specified locale (or union of locales).
217
+ *
218
+ * - Fallback to `MessageValue` if M is not LocaleMessages
219
+ */
220
+ type LocalizedLeafValue<M = unknown, K extends string = string, L extends keyof M | "union" = "union"> = M extends LocaleMessages ? L extends "union" ? LeafValue<M[keyof M], K> : LeafValue<M[Extract<L, keyof M>], K> : MessageValue;
204
221
 
205
222
  /**
206
223
  * Resolves the type at a dot-separated key in a nested object.
@@ -236,6 +253,21 @@ type MessagesAtPreKey<T, PK extends string> = PK extends `${infer Head}.${infer
236
253
  * ```
237
254
  */
238
255
  type ScopedLeafKeys<M, PK extends string, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer Messages ? Messages extends MessageValue ? MessagesAtPreKey<Messages, PK> extends infer Scoped ? Scoped extends MessageObject ? LeafKeys<Scoped, D> : never : never : never : never : string;
256
+ /**
257
+ * Resolves the value type of a scoped leaf key (`K`)
258
+ * under a prefix path (`PK`) from localized messages.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * const messages = {
263
+ * en: { a: { b: { c: "hello" }, z: [123] } },
264
+ * };
265
+ *
266
+ * ScopedLeafValue<typeof messages, "a", "z">; // number[]
267
+ * ScopedLeafValue<typeof messages, "a.b", "c">; // string
268
+ * ```
269
+ */
270
+ type ScopedLeafValue<M, PK extends string, K extends string, L extends keyof M | "union" = "union"> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer Messages ? Messages extends MessageValue ? MessagesAtPreKey<Messages, PK> extends infer Scoped ? Scoped extends MessageObject ? LeafValue<Scoped, K> : never : never : never : never : MessageValue;
239
271
 
240
272
  /**
241
273
  * Configuration options for translation behavior.
@@ -262,13 +294,13 @@ type TranslateHandlers = {
262
294
  formatHandler?: FormatHandler;
263
295
  };
264
296
  /** Function called when translation is still loading. */
265
- type LoadingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
297
+ type LoadingHandler = (ctx: HandlerContext) => MessageValue;
266
298
  /** Function called when no message is found for the given key. */
267
- type MissingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
299
+ type MissingHandler = (ctx: HandlerContext) => MessageValue;
268
300
  /** Function to format a resolved message. */
269
- type FormatHandler<Result = unknown> = (ctx: HandlerContext & {
301
+ type FormatHandler = (ctx: HandlerContext & {
270
302
  rawString: string;
271
- }) => Result;
303
+ }) => MessageValue;
272
304
  /**
273
305
  * Snapshot of the translate pipeline context exposed to handlers.
274
306
  *
@@ -281,10 +313,8 @@ type HandlerContext = Readonly<Omit<TranslateContext, "finalMessage">>;
281
313
 
282
314
  /**
283
315
  * Context object shared across the translate pipeline.
284
- *
285
- * @template Result - Final translated value type.
286
316
  */
287
- interface TranslateContext<Result = unknown> {
317
+ interface TranslateContext {
288
318
  /** Configuration for the translate pipeline. */
289
319
  config: TranslateConfig;
290
320
  /** Current messages for translation */
@@ -304,16 +334,16 @@ interface TranslateContext<Result = unknown> {
304
334
  /** Raw string message before formatting. */
305
335
  rawString?: string;
306
336
  /** Message after formatting (e.g. ICU, custom formatters) */
307
- formattedMessage?: unknown;
337
+ formattedMessage?: MessageValue;
308
338
  /** Final value produced by the pipeline */
309
- finalMessage?: Result;
339
+ finalMessage?: MessageValue;
310
340
  /** Free-form metadata shared between hooks. */
311
341
  meta: Record<string, unknown>;
312
342
  }
313
343
  /**
314
344
  * A single step in the translate pipeline.
315
345
  */
316
- type TranslateHook = RuraHook<TranslateContext>;
346
+ type TranslateHook = RuraHook<TranslateContext, MessageValue>;
317
347
 
318
348
  /**
319
349
  * Options for initializing a translator
@@ -406,21 +436,22 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, L ext
406
436
  /** Check if a key exists in the specified locale or current locale. */
407
437
  hasKey: <K extends LocalizedLeafKeys<M, L>>(key: K, targetLocale?: Locale<M>) => boolean;
408
438
  /** Get the translated message for a key, with optional replacements. */
409
- t: <Result = string, K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => Result;
439
+ t: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => LocalizedLeafValue<M, K, L>;
410
440
  /** Get the raw message value for a key without formatting or interpolation. */
411
- tRaw: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => MessageValue | undefined;
441
+ tRaw: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => LocalizedLeafValue<M, K, L>;
412
442
  }
413
443
 
414
444
  type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
415
- type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, L extends keyof M | "union" = "union", K = LocalizedLeafKeys<M, L>> = {
445
+ type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, L extends keyof M | "union" = "union", PK extends string | undefined = undefined, K extends string = PK extends string ? ScopedLeafKeys<M, PK, L> : LocalizedLeafKeys<M, L>> = {
416
446
  hasKey: (key?: K, targetLocale?: Locale<M>) => boolean;
417
- t: <Result = string>(key?: K, replacements?: Replacement) => Result;
447
+ t: <Key extends K>(key?: Key, replacements?: Replacement) => PK extends string ? ScopedLeafValue<M, PK, Key, L> : LocalizedLeafValue<M, Key, L>;
448
+ tRaw: <Key extends K>(key?: Key, replacements?: Replacement) => PK extends string ? ScopedLeafValue<M, PK, Key, L> : LocalizedLeafValue<M, Key, L>;
418
449
  };
419
450
 
420
451
  declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown, L extends keyof M | "union" = "union"> extends CoreTranslator<M> {
421
452
  constructor(options: ScopeTranslatorOptions<M>);
422
- /** Create a scoped translator with a prefix key, providing `t` and `hasKey` for nested keys. */
423
- scoped<PK extends LocalizedNodeKeys<M, L> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, L, ScopedLeafKeys<M, PK, L>> : ScopeTranslatorMethods<M, L>;
453
+ /** Create a scoped translator with a prefix key for resolving nested message paths. */
454
+ scoped<PK extends LocalizedNodeKeys<M, L> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, L, PK> : ScopeTranslatorMethods<M, L>;
424
455
  }
425
456
 
426
457
  /** Semantic tag attributes map. */
@@ -489,4 +520,4 @@ interface Renderer<Output> {
489
520
  */
490
521
  declare function renderRichMessage<Output>(message: string, renderer: Renderer<Output>): Output[];
491
522
 
492
- export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedMessagesUnion, type LocalizedNodeKeys, type MessageObject, type MessageValue, type MissingHandler, type NodeKeys, type Renderer, type Replacement, type ScopedLeafKeys, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, parseRichMessage, renderRichMessage };
523
+ export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LeafValue, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedLeafValue, type LocalizedMessagesUnion, type LocalizedNodeKeys, type MessageObject, type MessageValue, type MissingHandler, type NodeKeys, type Renderer, type Replacement, type ScopedLeafKeys, type ScopedLeafValue, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, parseRichMessage, renderRichMessage };
package/dist/index.js CHANGED
@@ -119,7 +119,7 @@ var loading = rura.createHook(
119
119
  };
120
120
  }
121
121
  const { loadingMessage } = config;
122
- if ("loadingMessage" in config) {
122
+ if (loadingMessage !== void 0) {
123
123
  return { early: true, output: loadingMessage };
124
124
  }
125
125
  },
@@ -138,7 +138,7 @@ var missing = rura.createHook(
138
138
  };
139
139
  }
140
140
  const { missingMessage } = config;
141
- if ("missingMessage" in config) {
141
+ if (missingMessage !== void 0) {
142
142
  return { early: true, output: missingMessage };
143
143
  }
144
144
  return { early: true, output: key };
@@ -174,6 +174,7 @@ var DEFAULT_HOOKS = [
174
174
  format,
175
175
  interpolate
176
176
  ];
177
+ rura.createPipeline(DEFAULT_HOOKS).debugHooks();
177
178
 
178
179
  // src/translators/base-translator/base-translator.ts
179
180
  var BaseTranslator = class {
@@ -248,12 +249,18 @@ function runTranslate(options) {
248
249
  function translate(options) {
249
250
  const { early, ctx, output } = runTranslate(options);
250
251
  if (early === true) return output;
252
+ if (ctx.finalMessage === void 0) {
253
+ throw new Error("Invariant violated: missing hook did not produce output");
254
+ }
251
255
  return ctx.finalMessage;
252
256
  }
253
257
 
254
258
  // src/translators/methods/translate-raw.ts
255
259
  function translateRaw(options) {
256
260
  const { ctx } = runTranslate(options);
261
+ if (ctx.rawValue === void 0) {
262
+ throw new Error("Invariant violated: missing hook did not produce output");
263
+ }
257
264
  return ctx.rawValue;
258
265
  }
259
266
 
@@ -338,7 +345,7 @@ var ScopeTranslator = class extends CoreTranslator {
338
345
  constructor(options) {
339
346
  super(options);
340
347
  }
341
- /** Create a scoped translator with a prefix key, providing `t` and `hasKey` for nested keys. */
348
+ /** Create a scoped translator with a prefix key for resolving nested message paths. */
342
349
  scoped(preKey) {
343
350
  return {
344
351
  hasKey: (key, targetLocale) => {
@@ -361,6 +368,18 @@ var ScopeTranslator = class extends CoreTranslator {
361
368
  key: fullKey,
362
369
  replacements
363
370
  });
371
+ },
372
+ tRaw: (key, replacements) => {
373
+ const fullKey = getFullKey(preKey, key);
374
+ return translateRaw({
375
+ hooks: this.hooks,
376
+ messages: this._messages,
377
+ locale: this._locale,
378
+ isLoading: this._isLoading,
379
+ translateConfig: this.translateConfig,
380
+ key: fullKey,
381
+ replacements
382
+ });
364
383
  }
365
384
  };
366
385
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intor-translator",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "🤖 A modern, type-safe i18n engine.",
5
5
  "author": {
6
6
  "name": "Yiming Liao",
@@ -62,7 +62,7 @@
62
62
  "examples:html:rich-message": "vite --config examples/html/rich-message/vite.config.ts"
63
63
  },
64
64
  "dependencies": {
65
- "rura": "1.0.7"
65
+ "rura": "^1.0.8"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/node": "24.10.1",