Skip to content

Commit 69914ea

Browse files
authored
fix: compile error for key with included hyphen in named interpolation (#1797)
resolve #1796
1 parent 96309d9 commit 69914ea

File tree

4 files changed

+84
-3
lines changed

4 files changed

+84
-3
lines changed

packages/message-compiler/src/tokenizer.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,16 @@ export function createTokenizer(
420420
return takeChar(scnr, closure)
421421
}
422422

423+
// NOTE: It is assumed that this function is used in conjunction with `takeIdentifierChar` for named.
424+
// TODO: we need to refactor this function ...
425+
function takeNamedIdentifierChar(scnr: Scanner): string | undefined | null {
426+
const closure = (ch: string) => {
427+
const cc = ch.charCodeAt(0)
428+
return cc === 45 // -
429+
}
430+
return takeChar(scnr, closure)
431+
}
432+
423433
function takeDigit(scnr: Scanner): string | undefined | null {
424434
const closure = (ch: string) => {
425435
const cc = ch.charCodeAt(0)
@@ -503,7 +513,8 @@ export function createTokenizer(
503513

504514
let ch: string | undefined | null = ''
505515
let name = ''
506-
while ((ch = takeIdentifierChar(scnr))) {
516+
// eslint-disable-next-line no-cond-assign
517+
while ((ch = takeIdentifierChar(scnr) || takeNamedIdentifierChar(scnr))) {
507518
name += ch
508519
}
509520

packages/message-compiler/test/tokenizer/named.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,57 @@ test('new line', () => {
310310
})
311311
})
312312

313+
test('include hyphen', () => {
314+
const tokenizer = createTokenizer('My Nickname is {nick-name}.')
315+
expect(tokenizer.nextToken()).toEqual({
316+
type: TokenTypes.Text,
317+
value: 'My Nickname is ',
318+
loc: {
319+
start: { line: 1, column: 1, offset: 0 },
320+
end: { line: 1, column: 16, offset: 15 }
321+
}
322+
})
323+
expect(tokenizer.nextToken()).toEqual({
324+
type: TokenTypes.BraceLeft,
325+
value: '{',
326+
loc: {
327+
start: { line: 1, column: 16, offset: 15 },
328+
end: { line: 1, column: 17, offset: 16 }
329+
}
330+
})
331+
expect(tokenizer.nextToken()).toEqual({
332+
type: TokenTypes.Named,
333+
value: 'nick-name',
334+
loc: {
335+
start: { line: 1, column: 17, offset: 16 },
336+
end: { line: 1, column: 26, offset: 25 }
337+
}
338+
})
339+
expect(tokenizer.nextToken()).toEqual({
340+
type: TokenTypes.BraceRight,
341+
value: '}',
342+
loc: {
343+
start: { line: 1, column: 26, offset: 25 },
344+
end: { line: 1, column: 27, offset: 26 }
345+
}
346+
})
347+
expect(tokenizer.nextToken()).toEqual({
348+
type: TokenTypes.Text,
349+
value: '.',
350+
loc: {
351+
start: { line: 1, column: 27, offset: 26 },
352+
end: { line: 1, column: 28, offset: 27 }
353+
}
354+
})
355+
expect(tokenizer.nextToken()).toEqual({
356+
type: TokenTypes.EOF,
357+
loc: {
358+
start: { line: 1, column: 28, offset: 27 },
359+
end: { line: 1, column: 28, offset: 27 }
360+
}
361+
})
362+
})
363+
313364
describe('modulo cases', () => {
314365
test('basic named: hi %{name} !', () => {
315366
const tokenizer = createTokenizer('hi %{name} !')

packages/vue-i18n-core/test/issues.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,3 +1358,21 @@ test('issue #1738', async () => {
13581358
expect(wrapper.find('#te1')?.textContent).toEqual(`true - expected true`)
13591359
expect(wrapper.find('#te2')?.textContent).toEqual(`true - expected true`)
13601360
})
1361+
1362+
test('#1796', async () => {
1363+
const i18n = createI18n({
1364+
locale: 'en',
1365+
messages: {
1366+
en: {
1367+
hello: 'hello world',
1368+
'message-with-placeholder-using-hyphens':
1369+
'My message with {placeholder-hyphens}.'
1370+
}
1371+
}
1372+
})
1373+
expect(
1374+
i18n.global.t('message-with-placeholder-using-hyphens', {
1375+
'placeholder-hyphens': i18n.global.t('hello')
1376+
})
1377+
).toEqual('My message with hello world.')
1378+
})

spec/syntax.ebnf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(*
2-
* Inltify message syntax v0.2
2+
* Inltify message syntax v0.3
33
* (vue-i18n compatible)
44
*)
55
@@ -14,7 +14,7 @@ Message ::= (Text? (Placeholder | Linked)? Text?)+;
1414
Text ::= TextChar+;
1515
Placeholder ::= Named | List | StringLiteral;
1616
Modulo ::= "%";
17-
Named ::= Modulo? "{" Space? (Identifier) Space? "}";
17+
Named ::= Modulo? "{" Space? (NamedIdentifier) Space? "}";
1818
List ::= "{" Space? (NumberLiteral) Space? "}";
1919
Linked ::= "@" (LinkedModifier)? LinkedDelimiter LinkedRefer;
2020
LinkedRefer ::= LinkedKey | Placeholder;
@@ -41,6 +41,7 @@ Digits ::= [0-9]+;
4141
4242
(* identifier *)
4343
Identifier ::= [a-zA-Z_] [a-zA-Z0-9_$]*;
44+
NamedIdentifier ::= [a-zA-Z_] [a-zA-Z0-9_\-$]*;
4445
4546
(* whitespaces *)
4647
SpaceInline ::= #x0020; (* "\u0020" *)

0 commit comments

Comments
 (0)