Skip to content

Commit

Permalink
fix: Use relative paths in .po file source comments
Browse files Browse the repository at this point in the history
Addresses the issue where file paths in .po file comments were absolute,
reflecting the local machine's directory structure.

Fixes vendure-ecommerce#63
  • Loading branch information
pmpak committed Nov 23, 2024
1 parent e33f036 commit 325f3c1
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 544 deletions.
492 changes: 0 additions & 492 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3",
"rimraf": "^5.0.5",
"tsx": "^4.19.2",
"typescript": "~5.2.2",
"vitest": "^1.3.1"
},
Expand Down
17 changes: 17 additions & 0 deletions src/utils/fs-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { basename, sep, posix } from 'node:path';

import * as os from 'os';
import * as fs from 'fs';
import braces from 'braces';
Expand All @@ -9,6 +11,21 @@ export function normalizeHomeDir(path: string): string {
return path;
}

/**
* Normalizes a file path by replacing the current working directory (`cwd`)
* with its base name and converting path separators to POSIX style.
*/
export function normalizeFilePath(filePath: string): string {
const cwd = 'process' in globalThis ? process.cwd() : '';
const cwdBaseName = basename(cwd);

if (!filePath.startsWith(cwd)) {
return filePath;
}

return filePath.replace(cwd, cwdBaseName).replaceAll(sep, posix.sep);
}

export function expandPattern(pattern: string): string[] {
return braces(pattern, { expand: true, keepEscaping: true });
}
Expand Down
7 changes: 4 additions & 3 deletions src/utils/translation.collection.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { normalizeFilePath } from './fs-helpers.js';

export interface TranslationType {
[key: string]: TranslationInterface;
}
Expand All @@ -18,16 +20,15 @@ export class TranslationCollection {
const translation = this.values[key]
? {...this.values[key]}
: {value: val, sourceFiles: []};
translation.sourceFiles.push(sourceFile);

translation.sourceFiles.push(normalizeFilePath(sourceFile));
return new TranslationCollection({...this.values, [key]: translation});
}

public addKeys(keys: string[], sourceFile: string): TranslationCollection {
const values = keys.reduce(
(results, key) => ({
...results,
[key]: <TranslationInterface>{value: '', sourceFiles: [sourceFile]}
[key]: <TranslationInterface>{value: '', sourceFiles: [normalizeFilePath(sourceFile)]}
}),
{} as TranslationType
);
Expand Down
89 changes: 89 additions & 0 deletions tests/cli/__snapshots__/cli.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`CLI Integration Tests > extracts translation keys to a .json file 1`] = `
"{
"translate-service.comp.welcome": "",
"translate-service.comp.description": "",
"translate-service.comp.details": "",
"translate-service.comp.show-more-label": "",
"translate-service.comp.show-less-label": "",
"pipe.comp.welcome": "",
"pipe.comp.description": "",
"directive.comp.welcome": "",
"directive.comp.description": "",
"private-translate-service.comp.welcome": "",
"private-translate-service.comp.description": "",
"ngx-translate.marker.dashboard.title": "",
"ngx-translate.marker.dashboard.description": "",
"marker.dashboard.title": "",
"marker.dashboard.description": ""
}"
`;

exports[`CLI Integration Tests > extracts translation keys to a .po file 1`] = `
"msgid ""
msgstr ""
"mime-version: 1.0\\n"
"Content-Type: text/plain; charset=utf-8\\n"
"Content-Transfer-Encoding: 8bit\\n"
#: ngx-translate-extract/tests/cli/fixtures/translate-service.component.fixture.ts
msgid "translate-service.comp.welcome"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-service.component.fixture.ts
msgid "translate-service.comp.description"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-service.component.fixture.ts
msgid "translate-service.comp.details"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-service.component.fixture.ts
msgid "translate-service.comp.show-more-label"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-service.component.fixture.ts
msgid "translate-service.comp.show-less-label"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-pipe.component.fixture.ts
msgid "pipe.comp.welcome"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-pipe.component.fixture.ts
msgid "pipe.comp.description"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-directive.component.fixture.ts
msgid "directive.comp.welcome"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/translate-directive.component.fixture.ts
msgid "directive.comp.description"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/private-translate-service.component.fixture.ts
msgid "private-translate-service.comp.welcome"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/private-translate-service.component.fixture.ts
msgid "private-translate-service.comp.description"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/ngx-translate.marker.fixture.ts
msgid "ngx-translate.marker.dashboard.title"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/ngx-translate.marker.fixture.ts
msgid "ngx-translate.marker.dashboard.description"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/marker.fixture.ts
msgid "marker.dashboard.title"
msgstr ""
#: ngx-translate-extract/tests/cli/fixtures/marker.fixture.ts
msgid "marker.dashboard.description"
msgstr """
`;
82 changes: 53 additions & 29 deletions tests/cli/cli.spec.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,66 @@
import { exec } from 'node:child_process';
import { readdir, readFile, rm } from 'node:fs/promises';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { readFileSync, rmSync } from 'node:fs';
import { promisify } from 'node:util';

import { afterEach, describe, expect, test } from 'vitest';
import { afterAll, beforeAll, describe, test } from 'vitest';

const execAsync = promisify(exec);
const __dirname = dirname(fileURLToPath(import.meta.url));

const REPOSITORY_ROOT = resolve(__dirname, '../..');
const CLI_PATH = resolve(REPOSITORY_ROOT, 'src/cli/cli.ts');
const FIXTURES_PATH = resolve(REPOSITORY_ROOT, 'tests/cli/fixtures/');
const OUTPUT_PATH = resolve(REPOSITORY_ROOT, 'tests/cli/fixtures/tmp');
const OUTPUT_FILE = resolve(OUTPUT_PATH, 'strings.json');
const TMP_PATH = resolve(REPOSITORY_ROOT, 'tests/cli/tmp');
const CLI_PATH = resolve(TMP_PATH, 'dist/cli/cli.js');

describe('CLI Integration Tests', () => {
afterEach(() => {
rmSync(OUTPUT_PATH, { recursive: true, force: true });
let nextFileId = 0;
const createUniqueFileName = (fileName: string) => resolve(TMP_PATH, `${nextFileId++}-${fileName}`);

describe.concurrent('CLI Integration Tests', () => {
beforeAll(async () => {
try {
await execAsync(`npm run build -- --outDir ${TMP_PATH}/dist`);
} catch (err) {
console.error('Error during build in beforeAll:', err);
throw err;
}
});

afterAll(async () => {
await rm(TMP_PATH, { recursive: true });
});

test('shows the expected output when extracting', async ({expect}) => {
const OUTPUT_FILE = createUniqueFileName('strings.json');
const fixtureFiles = await readdir(FIXTURES_PATH);
const { stdout } = await execAsync(`node ${CLI_PATH} --input ${FIXTURES_PATH} --output ${OUTPUT_FILE} --format=json`);

expect(stdout).toContain('Extracting:');
fixtureFiles.forEach(file => expect(stdout).toContain(file));

expect(stdout).toContain('Found 15 strings.');
expect(stdout).toContain('Saving:');

expect(stdout).toContain(OUTPUT_FILE);
expect(stdout).toContain('Done.');
})

test('extracts translation keys to a .json file', async ({ expect }) => {
const OUTPUT_FILE = createUniqueFileName('strings.json');
await execAsync(`node ${CLI_PATH} --input ${FIXTURES_PATH} --output ${OUTPUT_FILE} --format=json`);

const extracted = await readFile(OUTPUT_FILE, { encoding: 'utf8' });

expect(extracted).toMatchSnapshot();
});

test('extracts translation keys from a component', () =>
new Promise<void>((done) => {
exec(`npx tsx ${CLI_PATH} --input ${FIXTURES_PATH} --output ${OUTPUT_FILE}`, (error, stdout) => {
expect(error).toBeNull();
expect(stdout.trim()).toStrictEqual(expect.stringContaining('Extracting:'));
expect(stdout.trim()).toStrictEqual(expect.stringContaining('simple.component.fixture.ts'));
expect(stdout.trim()).toStrictEqual(expect.stringContaining('Found 2 strings.'));
expect(stdout.trim()).toStrictEqual(expect.stringContaining('Saving:'));
expect(stdout.trim()).toStrictEqual(expect.stringContaining('strings.json'));
expect(stdout.trim()).toStrictEqual(expect.stringContaining('Done.'));

const extracted = JSON.parse(readFileSync(OUTPUT_FILE, { encoding: 'utf8' }));
const extractedKeys = Object.keys(extracted);

expect(Object.keys(extracted).length).toBe(2);
expect(extractedKeys[0]).toBe('home.welcome');
expect(extractedKeys[1]).toBe('home.description');

done();
});
}));
test('extracts translation keys to a .po file', async ({ expect }) => {
const OUTPUT_FILE = createUniqueFileName('strings.po');
await execAsync(`node ${CLI_PATH} --input ${FIXTURES_PATH} --output ${OUTPUT_FILE} --format=pot`);

const extracted = await readFile(OUTPUT_FILE, { encoding: 'utf8' });

expect(extracted).toMatchSnapshot();
});
});
4 changes: 4 additions & 0 deletions tests/cli/fixtures/marker.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { marker } from '@biesbjerg/ngx-translate-extract-marker';

const title = marker('marker.dashboard.title');
const description = marker('marker.dashboard.description');
4 changes: 4 additions & 0 deletions tests/cli/fixtures/ngx-translate.marker.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { _ } from '@ngx-translate/core';

const title = _('ngx-translate.marker.dashboard.title');
const description = _('ngx-translate.marker.dashboard.description');
19 changes: 19 additions & 0 deletions tests/cli/fixtures/private-translate-service.component.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
selector: 'app-private-translate-service',
standalone: true,
template: `
<div>
<h1>{{ welcomeMessage }}</h1>
<p>{{ descriptionMessage }}</p>
</div>
`
})
export class PrivateTranslateServiceComponentFixture {
private readonly #translate = inject(TranslateService);

readonly welcomeMessage = this.#translate.instant('private-translate-service.comp.welcome');
readonly descriptionMessage = this.#translate.instant('private-translate-service.comp.description');
}
19 changes: 0 additions & 19 deletions tests/cli/fixtures/simple.component.fixture.ts

This file was deleted.

15 changes: 15 additions & 0 deletions tests/cli/fixtures/translate-directive.component.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component } from '@angular/core';
import { TranslateDirective } from '@ngx-translate/core';

@Component({
selector: 'app-home',
standalone: true,
imports: [TranslateDirective],
template: `
<div>
<h1 [translate]="'directive.comp.welcome'"></h1>
<p [translate]="'directive.comp.description'"></p>
</div>
`
})
export class TranslateDirectiveComponentFixture {}
15 changes: 15 additions & 0 deletions tests/cli/fixtures/translate-pipe.component.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component } from '@angular/core';
import { TranslatePipe } from "@ngx-translate/core";

@Component({
selector: 'app-home',
standalone: true,
imports: [TranslatePipe],
template: `
<div>
<h1>{{ 'pipe.comp.welcome' | translate }}</h1>
<p>{{ 'pipe.comp.description' | translate }}</p>
</div>
`
})
export class TranslatePipeComponentFixture {}
31 changes: 31 additions & 0 deletions tests/cli/fixtures/translate-service.component.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
selector: 'app-home',
standalone: true,
template: `
<div>
<h1>{{ welcomeMessage }}</h1>
<p>{{ descriptionMessage }}</p>
</div>
@if (showMore()) {
<button type="button" (click)="showMore.set(false)">{{ showLessLabel }}</button>
<p>{{ detailsMessage }}</p>
} @else {
<button type="button" (click)="showMore.set(true)">{{ showMoreLabel }}</button>
}
`
})
export class TranslateServiceComponentFixture {
private readonly translate = inject(TranslateService);

readonly welcomeMessage = this.translate.instant('translate-service.comp.welcome');
readonly descriptionMessage = this.translate.instant('translate-service.comp.description');
readonly detailsMessage = this.translate.instant('translate-service.comp.details');
readonly showMoreLabel = this.translate.instant('translate-service.comp.show-more-label');
readonly showLessLabel = this.translate.instant('translate-service.comp.show-less-label');

readonly showMore = signal(false);
}
Loading

0 comments on commit 325f3c1

Please sign in to comment.