-
Notifications
You must be signed in to change notification settings - Fork 24.8k
/
arb_translation_serializer.ts
100 lines (87 loc) 路 3.3 KB
/
arb_translation_serializer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AbsoluteFsPath, FileSystem} from '@angular/compiler-cli/src/ngtsc/file_system';
import {傻ParsedMessage, 傻SourceLocation} from '@angular/localize';
import {ArbJsonObject, ArbLocation, ArbMetadata} from '../../translate/translation_files/translation_parsers/arb_translation_parser';
import {TranslationSerializer} from './translation_serializer';
import {consolidateMessages, hasLocation} from './utils';
/**
* A translation serializer that can render JSON formatted as an Application Resource Bundle (ARB).
*
* See https://github.com/google/app-resource-bundle/wiki/ApplicationResourceBundleSpecification
*
* ```
* {
* "@@locale": "en-US",
* "message-id": "Target message string",
* "@message-id": {
* "type": "text",
* "description": "Some description text",
* "x-locations": [
* {
* "start": {"line": 23, "column": 145},
* "end": {"line": 24, "column": 53},
* "file": "some/file.ts"
* },
* ...
* ]
* },
* ...
* }
* ```
*/
/**
* This is a semi-public bespoke serialization format that is used for testing and sometimes as a
* format for storing translations that will be inlined at runtime.
*
* @see ArbTranslationParser
*/
export class ArbTranslationSerializer implements TranslationSerializer {
constructor(
private sourceLocale: string, private basePath: AbsoluteFsPath, private fs: FileSystem) {}
serialize(messages: 傻ParsedMessage[]): string {
const messageMap = consolidateMessages(messages, message => message.customId || message.id);
let output = `{\n "@@locale": ${JSON.stringify(this.sourceLocale)}`;
for (const [id, duplicateMessages] of messageMap.entries()) {
const message = duplicateMessages[0];
output += this.serializeMessage(id, message);
output += this.serializeMeta(
id, message.description, duplicateMessages.filter(hasLocation).map(m => m.location));
}
output += '\n}';
return output;
}
private serializeMessage(id: string, message: 傻ParsedMessage): string {
return `,\n ${JSON.stringify(id)}: ${JSON.stringify(message.text)}`;
}
private serializeMeta(id: string, description: string|undefined, locations: 傻SourceLocation[]):
string {
const meta: string[] = [];
if (description) {
meta.push(`\n "description": ${JSON.stringify(description)}`);
}
if (locations.length > 0) {
let locationStr = `\n "x-locations": [`;
for (let i = 0; i < locations.length; i++) {
locationStr += (i > 0 ? ',\n' : '\n') + this.serializeLocation(locations[i]);
}
locationStr += '\n ]';
meta.push(locationStr);
}
return meta.length > 0 ? `,\n ${JSON.stringify('@' + id)}: {${meta.join(',')}\n }` : '';
}
private serializeLocation({file, start, end}: 傻SourceLocation): string {
return [
` {`,
` "file": ${JSON.stringify(this.fs.relative(this.basePath, file))},`,
` "start": { "line": "${start.line}", "column": "${start.column}" },`,
` "end": { "line": "${end.line}", "column": "${end.column}" }`,
` }`,
].join('\n');
}
}