Skip to content

Commit 20629dd

Browse files
author
Sebi Nemeth
committed
dynamic encode and restore messages
1 parent 3b30279 commit 20629dd

File tree

2 files changed

+65
-56
lines changed

2 files changed

+65
-56
lines changed

dist/index.js

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -85,30 +85,13 @@ function deepForIn(object, fn) {
8585
};
8686
forIn(object, iteratee);
8787
}
88-
function encodeMessages(messagesObject, locale) {
89-
const messages = cloneDeep(messagesObject);
90-
deepForIn(messages, (message, path) => {
91-
const parts = message.split('|').map(part => part.trim());
92-
for (let i = 0; i < parts.length; i++) {
93-
const meta = ZeroWidthEncoder.encode(JSON.stringify({
94-
locale,
95-
message,
96-
path,
97-
choice: i || undefined,
98-
}));
99-
parts[i] = meta + parts[i];
100-
}
101-
set(messages, path, parts.join(' | '));
102-
});
103-
return messages;
104-
}
10588
class ZeroWidthEncoder {
10689
static START = '\u200B';
10790
static ZERO = '\u200C';
10891
static ONE = '\u200D';
10992
static SPACE = '\u200E';
11093
static END = '\u200F';
111-
static PATTERN = `${this.START}[${this.ZERO}${this.ONE}${this.SPACE}]+${this.END}`;
94+
static PATTERN = new RegExp(`${this.START}[${this.ZERO}${this.ONE}${this.SPACE}]+${this.END}`, 'gm');
11295
static encode(text) {
11396
const binary = text
11497
.split('')
@@ -218,11 +201,7 @@ class LiveTranslatorManager {
218201
this._box.classList.add('live-translator-box');
219202
this._wrapper.appendChild(this._box);
220203
// initialize encode
221-
for (const locale of this.i18n.availableLocales) {
222-
let messages = this.i18n.getLocaleMessage(locale);
223-
messages = encodeMessages(messages, locale);
224-
this.i18n.setLocaleMessage(locale, messages);
225-
}
204+
// moved to toggle()
226205
// initialize decode & render
227206
const throttler = throttle(() => this.render(), this._options.refreshRate || 50);
228207
const observer = new MutationObserver(throttler);
@@ -243,6 +222,32 @@ class LiveTranslatorManager {
243222
get i18n() {
244223
return this._options.i18n.global || this._options.i18n;
245224
}
225+
transformMessages(operation = 'encode') {
226+
for (const locale of this.i18n.availableLocales) {
227+
const messages = cloneDeep(this.i18n.getLocaleMessage(locale));
228+
deepForIn(messages, (message, path) => {
229+
const parts = message.split('|').map(part => part.trim());
230+
for (let i = 0; i < parts.length; i++) {
231+
switch (operation) {
232+
case 'encode':
233+
const meta = ZeroWidthEncoder.encode(JSON.stringify({
234+
locale,
235+
message,
236+
path,
237+
choice: i || undefined,
238+
}));
239+
parts[i] = meta + parts[i];
240+
break;
241+
case 'restore':
242+
parts[i] = parts[i].replaceAll(ZeroWidthEncoder.PATTERN, '');
243+
break;
244+
}
245+
}
246+
set(messages, path, parts.join(' | '));
247+
});
248+
this.i18n.setLocaleMessage(locale, messages);
249+
}
250+
}
246251
toggle(enable) {
247252
if (enable !== undefined) {
248253
this._enabled = enable;
@@ -257,20 +262,20 @@ class LiveTranslatorManager {
257262
if (!this._enabled) {
258263
this._cache.clear(true);
259264
}
265+
this.transformMessages(this._enabled ? 'encode' : 'restore');
260266
}
261267
render() {
262268
this._indicator.style.background = this._enabled ? 'lightgreen' : 'red';
263269
if (!this._enabled) {
264270
return;
265271
}
266-
const re = new RegExp(ZeroWidthEncoder.PATTERN, 'gm');
267272
const queue = [this.root];
268273
while (queue.length > 0) {
269274
const node = queue.pop();
270275
const badges = [];
271276
let cacheKeyParts = [];
272277
if (node instanceof Text) {
273-
const matches = node.textContent.match(re);
278+
const matches = node.textContent.match(ZeroWidthEncoder.PATTERN);
274279
for (const match of matches ?? []) {
275280
const meta = JSON.parse(ZeroWidthEncoder.decode(match));
276281
const badge = createBadge(meta, this._options, node);
@@ -281,7 +286,7 @@ class LiveTranslatorManager {
281286
}
282287
}
283288
const attributes = (node.attributes ? [...node.attributes] : [])
284-
.map((attribute) => ({ attribute, match: attribute.value.match(re) }))
289+
.map((attribute) => ({ attribute, match: attribute.value.match(ZeroWidthEncoder.PATTERN) }))
285290
.filter(({ match }) => !!match);
286291
for (const { attribute, match } of attributes) {
287292
for (const m of match) {

src/index.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -103,33 +103,13 @@ function deepForIn(object: Object, fn: (value: string, key: string) => void) {
103103
forIn(object, iteratee)
104104
}
105105

106-
function encodeMessages(messagesObject: object, locale: string) {
107-
const messages = cloneDeep(messagesObject)
108-
deepForIn(messages, (message, path) => {
109-
const parts = message.split('|').map(part => part.trim())
110-
for (let i = 0; i < parts.length; i++) {
111-
const meta = ZeroWidthEncoder.encode(
112-
JSON.stringify({
113-
locale,
114-
message,
115-
path,
116-
choice: i || undefined,
117-
} as TranslationMeta),
118-
)
119-
parts[i] = meta + parts[i]
120-
}
121-
set(messages, path, parts.join(' | '))
122-
})
123-
return messages
124-
}
125-
126106
abstract class ZeroWidthEncoder {
127107
static START = '\u200B'
128108
static ZERO = '\u200C'
129109
static ONE = '\u200D'
130110
static SPACE = '\u200E'
131111
static END = '\u200F'
132-
static PATTERN = `${this.START}[${this.ZERO}${this.ONE}${this.SPACE}]+${this.END}`
112+
static PATTERN = new RegExp(`${this.START}[${this.ZERO}${this.ONE}${this.SPACE}]+${this.END}`, 'gm')
133113

134114
static encode (text: string) {
135115
const binary = text
@@ -259,11 +239,7 @@ class LiveTranslatorManager {
259239
this._wrapper.appendChild(this._box)
260240

261241
// initialize encode
262-
for (const locale of this.i18n.availableLocales) {
263-
let messages = this.i18n.getLocaleMessage(locale)
264-
messages = encodeMessages(messages, locale)
265-
this.i18n.setLocaleMessage(locale, messages)
266-
}
242+
// moved to toggle()
267243

268244
// initialize decode & render
269245
const throttler = throttle(() => this.render(), this._options.refreshRate || 50)
@@ -291,6 +267,35 @@ class LiveTranslatorManager {
291267
return this._options.i18n.global || this._options.i18n
292268
}
293269

270+
transformMessages (operation: 'encode' | 'restore' = 'encode') {
271+
for (const locale of this.i18n.availableLocales) {
272+
const messages = cloneDeep(this.i18n.getLocaleMessage(locale))
273+
deepForIn(messages, (message, path) => {
274+
const parts = message.split('|').map(part => part.trim())
275+
for (let i = 0; i < parts.length; i++) {
276+
switch (operation) {
277+
case 'encode':
278+
const meta = ZeroWidthEncoder.encode(
279+
JSON.stringify({
280+
locale,
281+
message,
282+
path,
283+
choice: i || undefined,
284+
} as TranslationMeta),
285+
)
286+
parts[i] = meta + parts[i]
287+
break
288+
case 'restore':
289+
parts[i] = parts[i].replaceAll(ZeroWidthEncoder.PATTERN, '')
290+
break
291+
}
292+
}
293+
set(messages, path, parts.join(' | '))
294+
})
295+
this.i18n.setLocaleMessage(locale, messages)
296+
}
297+
}
298+
294299
toggle (enable?: boolean) {
295300
if (enable !== undefined) {
296301
this._enabled = enable
@@ -304,6 +309,7 @@ class LiveTranslatorManager {
304309
if (!this._enabled) {
305310
this._cache.clear(true)
306311
}
312+
this.transformMessages(this._enabled ? 'encode' : 'restore')
307313
}
308314

309315
render () {
@@ -313,8 +319,6 @@ class LiveTranslatorManager {
313319
return
314320
}
315321

316-
const re = new RegExp(ZeroWidthEncoder.PATTERN, 'gm')
317-
318322
const queue = [this.root] as Node[]
319323
while (queue.length > 0) {
320324
const node = queue.pop() as HTMLElement
@@ -324,7 +328,7 @@ class LiveTranslatorManager {
324328
let cacheKeyParts = []
325329

326330
if (node instanceof Text) {
327-
const matches = (node.textContent as string).match(re)
331+
const matches = (node.textContent as string).match(ZeroWidthEncoder.PATTERN)
328332
for (const match of matches ?? []) {
329333
const meta = JSON.parse(ZeroWidthEncoder.decode(match)) as TranslationMeta
330334
const badge = createBadge(meta, this._options, node)
@@ -336,7 +340,7 @@ class LiveTranslatorManager {
336340
}
337341

338342
const attributes = (node.attributes ? [...node.attributes] : [])
339-
.map((attribute) => ({ attribute, match: attribute.value.match(re) }))
343+
.map((attribute) => ({ attribute, match: attribute.value.match(ZeroWidthEncoder.PATTERN) }))
340344
.filter(({ match }) => !!match)
341345
for (const { attribute, match } of attributes) {
342346
for (const m of (match as RegExpMatchArray)) {

0 commit comments

Comments
 (0)