Skip to content

Commit

Permalink
Merge pull request #25 from PolymerLabs/xml
Browse files Browse the repository at this point in the history
Add <xliff> element, remove prettier formatting, release
  • Loading branch information
aomarks committed May 14, 2020
2 parents 98ff1eb + 60b6ce9 commit a4721f6
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 192 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- ## Unreleased -->

## [0.2.3] - 2020-05-13

- Fix missing `<xliff>` element in XLIFF output.
- Formatting change to XML output (e.g. fewer line breaks).

## [0.2.2] - 2020-05-13

- Fix incorrect path resolution when loading XLB files.
Expand Down
47 changes: 6 additions & 41 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lit-localize",
"version": "0.2.2",
"version": "0.2.3",
"description": "Localization for lit-html",
"license": "BSD-3-Clause",
"author": "The Polymer Project Authors",
Expand Down Expand Up @@ -28,13 +28,11 @@
"prepack": "npm run build"
},
"dependencies": {
"@prettier/plugin-xml": "^0.7.2",
"fs-extra": "^9.0.0",
"glob": "^7.1.6",
"jsonschema": "^1.2.6",
"minimist": "^1.2.5",
"parse5": "^6.0.0",
"prettier": "^2.0.5",
"source-map-support": "^0.5.19",
"typescript": "^3.8.3",
"xmldom": "^0.3.0"
Expand All @@ -47,7 +45,6 @@
"@types/minimist": "^1.2.0",
"@types/node": "^14.0.1",
"@types/parse5": "^5.0.2",
"@types/prettier": "^2.0.0",
"@types/xmldom": "^0.1.29",
"@typescript-eslint/eslint-plugin": "^2.30.0",
"@typescript-eslint/parser": "^2.30.0",
Expand All @@ -57,6 +54,7 @@
"dir-compare": "^2.3.0",
"eslint": "^7.0.0",
"lit-html": "^1.2.1",
"prettier": "^2.0.5",
"rimraf": "^3.0.2",
"typescript-json-schema": "^0.42.0"
}
Expand Down
57 changes: 9 additions & 48 deletions src/formatters/xlb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {ProgramMessage, Message, Bundle, Placeholder} from '../messages';
import {
getOneElementByTagNameOrThrow,
getNonEmptyAttributeOrThrow,
formatXml,
} from './xml-utils';

/**
Expand Down Expand Up @@ -147,12 +146,16 @@ class XlbFormatter implements Formatter {
*/
async writeOutput(sourceMessages: ProgramMessage[]): Promise<void> {
const doc = new xmldom.DOMImplementation().createDocument('', '', null);
const indent = (node: Element | Document, level = 0) =>
node.appendChild(doc.createTextNode('\n' + Array(level + 1).join(' ')));
doc.appendChild(
doc.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"')
);
indent(doc);
const bundle = doc.createElement('localizationbundle');
bundle.setAttribute('locale', this.config.sourceLocale);
doc.appendChild(bundle);
indent(bundle, 1);
const messagesNode = doc.createElement('messages');
bundle.appendChild(messagesNode);
for (const {name, contents, descStack} of sourceMessages) {
Expand All @@ -161,6 +164,7 @@ class XlbFormatter implements Formatter {
if (descStack.length > 0) {
messageNode.setAttribute('desc', descStack.join(' / '));
}
indent(messagesNode, 2);
messagesNode.appendChild(messageNode);
for (const content of contents) {
if (typeof content === 'string') {
Expand All @@ -173,57 +177,14 @@ class XlbFormatter implements Formatter {
}
}
}
indent(messagesNode, 1);
indent(bundle);
indent(doc);
const serialized = new xmldom.XMLSerializer().serializeToString(doc);
const formatted = formatXml(serialized);
await fsExtra.writeFile(
this.config.resolve(this.xlbConfig.outputFile),
formatted,
serialized,
'utf8'
);
}
}

/**
* Generate an XLB XML file for the given messages. This file contains the
* canonical set of messages that will be translatd.
*/
export function generateXlb(
messages: ProgramMessage[],
locale: Locale
): string {
const doc = new xmldom.DOMImplementation().createDocument('', '', null);
doc.appendChild(
doc.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"')
);
doc.appendChild(doc.createTextNode('\n'));
const bundle = doc.createElement('localizationbundle');
bundle.setAttribute('locale', locale);
doc.appendChild(bundle);
bundle.appendChild(doc.createTextNode('\n '));
const messagesNode = doc.createElement('messages');
bundle.appendChild(messagesNode);
for (const {name, contents, descStack} of messages) {
messagesNode.appendChild(doc.createTextNode('\n '));
const messageNode = doc.createElement('msg');
messageNode.setAttribute('name', name);
if (descStack.length > 0) {
messageNode.setAttribute('desc', descStack.join(' / '));
}
messagesNode.appendChild(messageNode);
for (const content of contents) {
if (typeof content === 'string') {
messageNode.appendChild(doc.createTextNode(content));
} else {
const {untranslatable} = content;
const ph = doc.createElement('ph');
ph.appendChild(doc.createTextNode(untranslatable));
messageNode.appendChild(ph);
}
}
}
messagesNode.appendChild(doc.createTextNode('\n '));
bundle.appendChild(doc.createTextNode('\n'));
doc.appendChild(doc.createTextNode('\n'));
const serialized = new xmldom.XMLSerializer().serializeToString(doc);
return serialized;
}
25 changes: 19 additions & 6 deletions src/formatters/xliff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {Bundle, Message, ProgramMessage, Placeholder} from '../messages';
import {
getOneElementByTagNameOrThrow,
getNonEmptyAttributeOrThrow,
formatXml,
} from './xml-utils';

/**
Expand Down Expand Up @@ -187,10 +186,12 @@ export class XliffFormatter implements Formatter {
}

const doc = new xmldom.DOMImplementation().createDocument('', '', null);
const indent = (node: Element | Document, level = 0) =>
node.appendChild(doc.createTextNode('\n' + Array(level + 1).join(' ')));
doc.appendChild(
doc.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"')
);
doc.appendChild(doc.createTextNode('\n'));
indent(doc);

// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#xliff
const xliff = doc.createElement('xliff');
Expand All @@ -200,27 +201,33 @@ export class XliffFormatter implements Formatter {
'xsi:schemaLocation',
'urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-strict.xsd'
);
doc.appendChild(xliff);
indent(xliff);

// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#file
const file = doc.createElement('file');
doc.appendChild(file);
xliff.appendChild(file);
file.setAttribute('target-language', targetLocale);
file.setAttribute('source-language', this.config.sourceLocale);
// TODO The spec requires the source filename in the "original" attribute,
// but we don't currently track filenames.
file.setAttribute('original', 'lit-localize-inputs');
// Plaintext seems right, as opposed to HTML, since our translatable
// message text is just text, and all HTML markup is encoded into <ph>
// elements.
file.setAttribute('datatype', 'plaintext');
file.setAttribute('source-language', this.config.sourceLocale);
file.setAttribute('target-language', targetLocale);
indent(file);

// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#body
const body = doc.createElement('body');
file.appendChild(body);
indent(body);

for (const {name, contents: sourceContents, descStack} of sourceMessages) {
// https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#trans-unit
const transUnit = doc.createElement('trans-unit');
body.appendChild(transUnit);
indent(transUnit, 1);
transUnit.setAttribute('id', name);

if (descStack.length > 0) {
Expand All @@ -244,12 +251,18 @@ export class XliffFormatter implements Formatter {
for (const child of this.encodeContents(doc, translation.contents)) {
target.appendChild(child);
}
indent(transUnit, 1);
transUnit.appendChild(target);
}
indent(transUnit);
indent(body);
}
indent(file);
indent(xliff);
indent(doc);
const serializer = new xmldom.XMLSerializer();
const xmlStr = serializer.serializeToString(doc);
return formatXml(xmlStr);
return xmlStr;
}

/**
Expand Down
14 changes: 0 additions & 14 deletions src/formatters/xml-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
* rights grant found at http://polymer.github.io/PATENTS.txt
*/

import * as prettier from 'prettier';

/**
* Query the given parent element for a descendent with the given tag name and
* return it, or throw if none or more than one are found.
Expand Down Expand Up @@ -46,15 +44,3 @@ export function getNonEmptyAttributeOrThrow(
}
return attribute;
}

/**
* Format the given serialized XML using Prettier.
*/
export function formatXml(xmlStr: string): string {
// TODO(aomarks) Types for the xml-parser plugin.
return prettier.format(xmlStr, ({
plugins: ['@prettier/plugin-xml'],
parser: 'xml',
xmlWhitespaceSensitivity: 'ignore',
} as unknown) as prettier.Options);
}
8 changes: 3 additions & 5 deletions testdata/xlb/goldens/xlb/en.xlb
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<localizationbundle locale="en">
<messages>
<msg name="string">Hello World!</msg>
<msg name="lit">Hello <ph>&lt;b>&lt;i></ph>World!<ph
>&lt;/i>&lt;/b></ph></msg>
<msg name="lit">Hello <ph>&lt;b>&lt;i></ph>World!<ph>&lt;/i>&lt;/b></ph></msg>
<msg name="variables_1">Hello <ph>${name}</ph>!</msg>
<msg name="lit_variables_1">Hello <ph>${name}</ph>, click <ph
>&lt;a href="${url}"></ph>here<ph>&lt;/a></ph>!</msg>
<msg name="lit_variables_1">Hello <ph>${name}</ph>, click <ph>&lt;a href="${url}"></ph>here<ph>&lt;/a></ph>!</msg>
<msg name="lit_variables_2"><ph>${x}</ph>y<ph>${x}</ph>y<ph>${x}</ph></msg>
<msg name="lit_variables_3"><ph>&lt;b>
${x}
Expand Down

0 comments on commit a4721f6

Please sign in to comment.