Skip to content

Commit da1ffb5

Browse files
committed
fix(): unicode chars were removed from .po files when extracting
1 parent 3b449b7 commit da1ffb5

7 files changed

Lines changed: 28 additions & 9 deletions

File tree

packages/conf/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { GeneratorOptions } from "@babel/core";
22

3+
export const UNICODE_REGEX: RegExp
34
export declare type CatalogFormat = "lingui" | "minimal" | "po" | "csv" | "po-gettext";
45
export type CatalogFormatOptions = {
56
origins?: boolean;

packages/conf/src/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import type { GeneratorOptions } from "@babel/core"
22
import path from "path"
33
import fs from "fs"
44
import chalk from "chalk"
5-
import { Loader, cosmiconfigSync } from "cosmiconfig"
5+
import { cosmiconfigSync } from "cosmiconfig"
66
import { multipleValidOptions, validate } from "jest-validate"
7-
import get from "lodash.get"
8-
7+
// This regex will detect if a string contains unicode chars, when they're we should interpolate them
8+
// why? because platforms like react native doesn't parse them, just doing a JSON.parse makes them UTF-8 friendly
9+
export const UNICODE_REGEX = /\\u[a-fA-F0-9]{4}|\\x[a-fA-F0-9]{2}/g;
910
export type CatalogFormat = "lingui" | "minimal" | "po" | "csv"
1011

1112
export type CatalogFormatOptions = {

packages/core/src/context.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { CompiledMessage, Locales } from "./i18n"
22
import { date, number } from "./formats"
33
import { isString, isFunction } from "./essentials"
44

5+
export const UNICODE_REGEX = /\\u[a-fA-F0-9]{4}|\\x[a-fA-F0-9]{2}/g;
6+
57
const defaultFormats = (
68
locale,
79
locales,
@@ -111,7 +113,7 @@ export function interpolate(
111113
}
112114

113115
const result = formatMessage(translation)
114-
if (isString(result) && /\\u[a-fA-F0-9]{4}/g.test(result)) return JSON.parse(`"${result.trim()}"`)
116+
if (isString(result) && UNICODE_REGEX.test(result)) return JSON.parse(`"${result.trim()}"`)
115117
if (isString(result)) return result.trim()
116118
return result
117119
}

packages/core/src/i18n.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { interpolate } from "./context"
1+
import { interpolate, UNICODE_REGEX } from "./context"
22
import { isString, isFunction } from "./essentials"
33
import { date, number } from "./formats"
44
import * as icu from "./dev"
@@ -193,7 +193,7 @@ export class I18n extends EventEmitter<Events> {
193193

194194

195195
// hack for parsing unicode values inside a string to get parsed in react native environments
196-
if (isString(translation) && /\\u[a-fA-F0-9]{4}/g.test(translation)) return JSON.parse(`"${translation}"`) as string;
196+
if (isString(translation) && UNICODE_REGEX.test(translation)) return JSON.parse(`"${translation}"`) as string;
197197
if (isString(translation)) return translation
198198

199199
return interpolate(

packages/macro/src/macroJs.test.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ describe("js macro", () => {
8080
])
8181
})
8282

83-
it("message with unicode chars is interpreted by babel", () => {
83+
it("message with unicode \\u chars is interpreted by babel", () => {
8484
const macro = createMacro()
8585
const exp = parseExpression('t`Message \\u0020`')
8686
const tokens = macro.tokenizeTemplateLiteral(exp)
@@ -92,6 +92,19 @@ describe("js macro", () => {
9292
])
9393
})
9494

95+
it("message with unicode \\x chars is interpreted by babel", () => {
96+
const macro = createMacro()
97+
const exp = parseExpression('t`Bienvenue\\xA0!`')
98+
const tokens = macro.tokenizeTemplateLiteral(exp)
99+
expect(tokens).toEqual([
100+
{
101+
type: "text",
102+
// Looks like an empty space, but it isn't
103+
value: 'Bienvenue !',
104+
},
105+
])
106+
})
107+
95108
it("message with double scaped literals it's stripped", () => {
96109
const macro = createMacro()
97110
const exp = parseExpression('t\`Passing \\`${argSet}\\` is not supported.\`')

packages/macro/src/macroJs.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as R from "ramda"
22
import * as babelTypes from "@babel/types"
33
import { NodePath } from "@babel/traverse"
4+
import { UNICODE_REGEX } from "@lingui/conf"
45

56
import ICUMessageFormat from "./icu"
67
import { zip, makeCounter } from "./utils"
@@ -265,7 +266,7 @@ export default class MacroJs {
265266
quasis: R.map((text: babelTypes.TemplateElement) => {
266267
// Don't output tokens without text.
267268
// if it's an unicode we keep the cooked value because it's the parsed value by babel (without unicode chars)
268-
const value = /\\u[a-fA-F0-9]{4}/g.test(text.value.raw) ? text.value.cooked : text.value.raw
269+
const value = UNICODE_REGEX.test(text.value.raw) ? text.value.cooked : text.value.raw
269270
if (value === "") return null
270271

271272
return {

packages/macro/src/macroJsx.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as R from "ramda"
22
import * as babelTypes from "@babel/types"
33
import { NodePath } from "@babel/traverse"
4+
import { UNICODE_REGEX } from "@lingui/conf"
45

56
import ICUMessageFormat from "./icu"
67
import { zip, makeCounter } from "./utils"
@@ -231,7 +232,7 @@ export default class MacroJSX {
231232
R.evolve({
232233
quasis: R.map((text: babelTypes.TemplateElement) => {
233234
// Don"t output tokens without text.
234-
const value = /\\u[a-fA-F0-9]{4}/g.test(text.value.raw) ? text.value.cooked : text.value.raw
235+
const value = UNICODE_REGEX.test(text.value.raw) ? text.value.cooked : text.value.raw
235236
if (value === "") return null
236237

237238
return this.tokenizeText(this.clearBackslashes(value))

0 commit comments

Comments
 (0)