transduck 0.4.0 → 0.4.1

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/dist/cli.js CHANGED
@@ -454,7 +454,7 @@ export async function runStats(opts) {
454
454
  }
455
455
  // CLI entry point
456
456
  const program = new Command();
457
- program.name('transduck').description('AI-native translation tool').version('0.4.0');
457
+ program.name('transduck').description('AI-native translation tool').version('0.4.1');
458
458
  program.command('init')
459
459
  .description('Initialize a new transduck project')
460
460
  .action(async () => {
@@ -35,6 +35,7 @@ export function useTransDuck() {
35
35
  };
36
36
  }
37
37
  export function _resetReactState() {
38
+ flushScheduled = false;
38
39
  _state = {
39
40
  language: '',
40
41
  sourceLang: 'EN',
@@ -62,6 +63,19 @@ function interpolateVars(text, vars) {
62
63
  }
63
64
  return result;
64
65
  }
66
+ // --- Self-flushing microtask scheduler ---
67
+ // Ensures pending strings are fetched even when the provider doesn't re-render
68
+ // (e.g., client-side navigation in Next.js App Router persistent layouts).
69
+ let flushScheduled = false;
70
+ function schedulePendingFlush() {
71
+ if (flushScheduled || !_state.triggerFetch || _state.isLanguageSwitch)
72
+ return;
73
+ flushScheduled = true;
74
+ queueMicrotask(() => {
75
+ flushScheduled = false;
76
+ _state.triggerFetch?.();
77
+ });
78
+ }
65
79
  // --- Stable exported functions ---
66
80
  export function t(sourceText, context, vars) {
67
81
  const key = `${sourceText}||${context ?? ''}`;
@@ -75,8 +89,9 @@ export function t(sourceText, context, vars) {
75
89
  if (cached !== undefined) {
76
90
  return interpolateVars(cached, vars);
77
91
  }
78
- // Queue for fetch (useEffect in provider will flush after render)
92
+ // Queue for fetch
79
93
  _state.pendingStrings.add(key);
94
+ schedulePendingFlush();
80
95
  // Return source text as fallback
81
96
  return interpolateVars(sourceText, vars);
82
97
  }
@@ -109,8 +124,9 @@ export function tPlural(one, other, count, opts) {
109
124
  const form = cachedForms[category] ?? cachedForms['other'] ?? other;
110
125
  return interpolateVars(form, vars);
111
126
  }
112
- // Queue for fetch (useEffect in provider will flush after render)
127
+ // Queue for fetch
113
128
  _state.pendingPlurals.add(cacheKey);
129
+ schedulePendingFlush();
114
130
  // Fallback to source form
115
131
  const rules = new Intl.PluralRules(_state.sourceLang.toLowerCase());
116
132
  const form = rules.select(count) === 'one' ? one : other;
package/dist/storage.js CHANGED
@@ -29,7 +29,7 @@ export class TranslationStore {
29
29
  this.db = open({
30
30
  path: this.dbPath,
31
31
  mapSize: DEFAULT_MAP_SIZE,
32
- // Use msgpack (default) for efficient storage
32
+ encoding: 'json',
33
33
  });
34
34
  }
35
35
  getDb() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "transduck",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "AI-native translation tool using source text as keys",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/cli.ts CHANGED
@@ -562,7 +562,7 @@ export async function runStats(opts: StatsOptions): Promise<string> {
562
562
  // CLI entry point
563
563
  const program = new Command();
564
564
 
565
- program.name('transduck').description('AI-native translation tool').version('0.4.0');
565
+ program.name('transduck').description('AI-native translation tool').version('0.4.1');
566
566
 
567
567
  program.command('init')
568
568
  .description('Initialize a new transduck project')
@@ -82,6 +82,7 @@ export function useTransDuck(): UseTransDuckReturn {
82
82
  }
83
83
 
84
84
  export function _resetReactState(): void {
85
+ flushScheduled = false;
85
86
  _state = {
86
87
  language: '',
87
88
  sourceLang: 'EN',
@@ -111,6 +112,21 @@ function interpolateVars(text: string, vars?: Record<string, string | number> |
111
112
  return result;
112
113
  }
113
114
 
115
+ // --- Self-flushing microtask scheduler ---
116
+ // Ensures pending strings are fetched even when the provider doesn't re-render
117
+ // (e.g., client-side navigation in Next.js App Router persistent layouts).
118
+
119
+ let flushScheduled = false;
120
+
121
+ function schedulePendingFlush() {
122
+ if (flushScheduled || !_state.triggerFetch || _state.isLanguageSwitch) return;
123
+ flushScheduled = true;
124
+ queueMicrotask(() => {
125
+ flushScheduled = false;
126
+ _state.triggerFetch?.();
127
+ });
128
+ }
129
+
114
130
  // --- Stable exported functions ---
115
131
 
116
132
  export function t(
@@ -132,8 +148,9 @@ export function t(
132
148
  return interpolateVars(cached, vars);
133
149
  }
134
150
 
135
- // Queue for fetch (useEffect in provider will flush after render)
151
+ // Queue for fetch
136
152
  _state.pendingStrings.add(key);
153
+ schedulePendingFlush();
137
154
 
138
155
  // Return source text as fallback
139
156
  return interpolateVars(sourceText, vars);
@@ -175,8 +192,9 @@ export function tPlural(
175
192
  return interpolateVars(form, vars);
176
193
  }
177
194
 
178
- // Queue for fetch (useEffect in provider will flush after render)
195
+ // Queue for fetch
179
196
  _state.pendingPlurals.add(cacheKey);
197
+ schedulePendingFlush();
180
198
 
181
199
  // Fallback to source form
182
200
  const rules = new Intl.PluralRules(_state.sourceLang.toLowerCase());
package/src/storage.ts CHANGED
@@ -73,7 +73,7 @@ export class TranslationStore {
73
73
  this.db = open<StoredEntry, string>({
74
74
  path: this.dbPath,
75
75
  mapSize: DEFAULT_MAP_SIZE,
76
- // Use msgpack (default) for efficient storage
76
+ encoding: 'json',
77
77
  });
78
78
  }
79
79