Tests about support of HTML tags in translations keys with GetText (#172)
- Verify that html tags are supported in translation keys - Add typed support of gettext-parser
This commit is contained in:
		| @@ -100,3 +100,7 @@ Examples: | |||||||
|   ngx-translate-extract -i './src/**/*.{ts,tsx,html}' -o strings.json     Extract from ts, tsx and html |   ngx-translate-extract -i './src/**/*.{ts,tsx,html}' -o strings.json     Extract from ts, tsx and html | ||||||
|   ngx-translate-extract -i './src/**/!(*.spec).{ts,html}' -o              Extract from ts, html, excluding files with ".spec" |   ngx-translate-extract -i './src/**/!(*.spec).{ts,html}' -o              Extract from ts, html, excluding files with ".spec" | ||||||
|   strings.json |   strings.json | ||||||
|  |  | ||||||
|  | ## Note for GetText users | ||||||
|  |  | ||||||
|  | Please pay attention of which version of `gettext-parser` you actually use in your project. For instance, `gettext-parser:1.2.2` does not support HTML tags in translation keys. | ||||||
							
								
								
									
										9
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -136,6 +136,15 @@ | |||||||
|       "integrity": "sha512-GcgAp7RXXGmA61spVEKZYpIy3/iV6GHbTW9f9kaKwHVQgnWitt6X026e+3N6j8ep1bkIWj83qPHQ3Y9Ft8FqiQ==", |       "integrity": "sha512-GcgAp7RXXGmA61spVEKZYpIy3/iV6GHbTW9f9kaKwHVQgnWitt6X026e+3N6j8ep1bkIWj83qPHQ3Y9Ft8FqiQ==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|  |     "@types/gettext-parser": { | ||||||
|  |       "version": "4.0.0", | ||||||
|  |       "resolved": "https://registry.npmjs.org/@types/gettext-parser/-/gettext-parser-4.0.0.tgz", | ||||||
|  |       "integrity": "sha512-I/wvhr+l5M7IwBF1ADBfNQ6qGfUg85UTjj/AZWn09Y+POqyLe1cfbdJSMWzCobiJ3EJNY23MQCbP6jxQT81OTQ==", | ||||||
|  |       "dev": true, | ||||||
|  |       "requires": { | ||||||
|  |         "@types/node": "*" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "@types/glob": { |     "@types/glob": { | ||||||
|       "version": "7.1.1", |       "version": "7.1.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", |       "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", | ||||||
|   | |||||||
| @@ -69,6 +69,7 @@ | |||||||
|     "@types/mocha": "^7.0.2", |     "@types/mocha": "^7.0.2", | ||||||
|     "@types/node": "^12.12.31", |     "@types/node": "^12.12.31", | ||||||
|     "@types/yargs": "^15.0.4", |     "@types/yargs": "^15.0.4", | ||||||
|  |     "@types/gettext-parser": "4.0.0", | ||||||
|     "braces": "^3.0.2", |     "braces": "^3.0.2", | ||||||
|     "chai": "^4.2.0", |     "chai": "^4.2.0", | ||||||
|     "husky": "^4.2.3", |     "husky": "^4.2.3", | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { CompilerInterface } from './compiler.interface'; | import { CompilerInterface } from './compiler.interface'; | ||||||
| import { TranslationCollection, TranslationType } from '../utils/translation.collection'; | import { TranslationCollection, TranslationType } from '../utils/translation.collection'; | ||||||
|  |  | ||||||
| import * as gettext from 'gettext-parser'; | import { po } from 'gettext-parser'; | ||||||
|  |  | ||||||
| export class PoCompiler implements CompilerInterface { | export class PoCompiler implements CompilerInterface { | ||||||
| 	public extension: string = 'po'; | 	public extension: string = 'po'; | ||||||
| @@ -34,23 +34,24 @@ export class PoCompiler implements CompilerInterface { | |||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		return gettext.po.compile(data); | 		return po.compile(data).toString('utf8'); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public parse(contents: string): TranslationCollection { | 	public parse(contents: string): TranslationCollection { | ||||||
| 		const collection = new TranslationCollection(); | 		const collection = new TranslationCollection(); | ||||||
|  |  | ||||||
| 		const po = gettext.po.parse(contents, 'utf8'); | 		const parsedPo = po.parse(contents, 'utf8'); | ||||||
| 		if (!po.translations.hasOwnProperty(this.domain)) { |  | ||||||
|  | 		if (!parsedPo.translations.hasOwnProperty(this.domain)) { | ||||||
| 			return collection; | 			return collection; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		const values = Object.keys(po.translations[this.domain]) | 		const values = Object.keys(parsedPo.translations[this.domain]) | ||||||
| 			.filter((key) => key.length > 0) | 			.filter((key) => key.length > 0) | ||||||
| 			.reduce((result, key) => { | 			.reduce((result, key) => { | ||||||
| 				return { | 				return { | ||||||
| 					...result, | 					...result, | ||||||
| 					[key]: po.translations[this.domain][key].msgstr.pop() | 					[key]: parsedPo.translations[this.domain][key].msgstr.pop() | ||||||
| 				}; | 				}; | ||||||
| 			}, {} as TranslationType); | 			}, {} as TranslationType); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								src/declarations.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/declarations.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | |||||||
| declare module 'gettext-parser'; |  | ||||||
							
								
								
									
										24
									
								
								tests/compilers/po.compiler.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/compilers/po.compiler.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | import { expect } from 'chai'; | ||||||
|  |  | ||||||
|  | import { TranslationCollection } from '../../src/utils/translation.collection'; | ||||||
|  | import { PoCompiler } from '../../src/compilers/po.compiler'; | ||||||
|  |  | ||||||
|  | describe('PoCompiler', () => { | ||||||
|  | 	let compiler: PoCompiler; | ||||||
|  |  | ||||||
|  | 	beforeEach(() => { | ||||||
|  | 		compiler = new PoCompiler(); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	it('should still include html ', () => { | ||||||
|  | 		const collection = new TranslationCollection({ | ||||||
|  | 			'A <strong>test</strong>': 'Un <strong>test</strong>', | ||||||
|  | 			'With a lot of <em>html</em> included': 'Avec beaucoup d\'<em>html</em> inclus' | ||||||
|  | 		}); | ||||||
|  | 		const result: Buffer = Buffer.from(compiler.compile(collection)); | ||||||
|  | 		expect(result.toString('utf8')).to.equal('msgid ""\nmsgstr ""\n"mime-version: 1.0\\n"\n"Content-Type: text/plain; charset=utf-8\\n"\n"Content-Transfer-Encoding: 8bit\\n"\n\nmsgid "A <strong>test</strong>"\nmsgstr "Un <strong>test</strong>"\n\nmsgid "With a lot of <em>html</em> included"\nmsgstr "Avec beaucoup d\'<em>html</em> inclus"'); | ||||||
|  | 	}); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -36,6 +36,12 @@ describe('DirectiveParser', () => { | |||||||
| 		expect(keys).to.deep.equal(['Hello <strong translate>World</strong>']); | 		expect(keys).to.deep.equal(['Hello <strong translate>World</strong>']); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | 	it('should not exclude html tags in children', () => { | ||||||
|  | 		const contents = `<div translate>Hello <strong>World</strong></div>`; | ||||||
|  | 		const keys = parser.extract(contents, templateFilename).keys(); | ||||||
|  | 		expect(keys).to.deep.equal(['Hello <strong>World</strong>']); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
| 	it('should extract and parse inline template', () => { | 	it('should extract and parse inline template', () => { | ||||||
| 		const contents = ` | 		const contents = ` | ||||||
| 			@Component({ | 			@Component({ | ||||||
|   | |||||||
| @@ -36,6 +36,17 @@ describe('MarkerParser', () => { | |||||||
| 		expect(keys).to.deep.equal(['Hello world', 'This is a very very very very long line.', 'Mix of different types']); | 		expect(keys).to.deep.equal(['Hello world', 'This is a very very very very long line.', 'Mix of different types']); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | 	it('should extract split strings while keeping html tags', () => { | ||||||
|  | 		const contents = ` | ||||||
|  | 			import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; | ||||||
|  | 			_('Hello ' + 'world'); | ||||||
|  | 			_('This <em>is</em> a ' + 'very ' + 'very ' + 'very ' + 'very ' + 'long line.'); | ||||||
|  | 			_('Mix ' + \`of \` + 'different ' + \`types\`); | ||||||
|  | 		`; | ||||||
|  | 		const keys = parser.extract(contents, componentFilename).keys(); | ||||||
|  | 		expect(keys).to.deep.equal(['Hello world', 'This <em>is</em> a very very very very long line.', 'Mix of different types']); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
| 	it('should extract the strings', () => { | 	it('should extract the strings', () => { | ||||||
| 		const contents = ` | 		const contents = ` | ||||||
| 		import { marker } from '@biesbjerg/ngx-translate-extract-marker'; | 		import { marker } from '@biesbjerg/ngx-translate-extract-marker'; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user