Skip to content

Commit

Permalink
XLIFF Sync - New Build with Translations command (#122)
Browse files Browse the repository at this point in the history
* added buildWithTranslations command

* delete

* added buildWithTranslations command

* Update README-CUSTOM.md

* bugfix + settings order

* updated version

* renmaned readme-custom

* applied commented issues

* removed readme-custom from changelog

* revert removed svg images

* renamed files + use of WorkspaceHelper

* remove language settings pattern

* build with translation: build + sync

* Updates for Build with Translations command

---------

Co-authored-by: Rob van Bekkum <[email protected]>
  • Loading branch information
FlorianNoeverGOB and rvanbekkum authored Aug 16, 2024
1 parent 29eec87 commit 6d7a2f4
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 81 deletions.
9 changes: 4 additions & 5 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
"presentation": {
"reveal": "never"
},
"group": {
"kind": "build",
"isDefault": true
}
"group": "build",
"label": "npm: watch",
"detail": "tsc -watch -p ./"
}
]
}
}
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [1.5.0] 15-08-2024

* New command `xliffSync.buildWithTranslations` which first builds the project in the currently open workspace/project folder, and directly afterwards synchronizes all .xlf translation files in the workspace/project folder.
* New setting `xliffSync.defaultLanguages` that can be used to specify the languages that should automatically be used for the translation file generation.
* New setting `xliffSync.buildCommandToExecute` that specifies the build command to execute for the `xliffSync.buildWithTranslations` command

### Thank You

* **[FlorianNoeverGOB](https://github.com/FlorianNoeverGOB)** for your pull request to add the `xliffSync.buildWithTranslations` command (Pull Request [#122](https://github.com/rvanbekkum/vsc-xliff-sync/pull/122))

## [1.4.0] 30-12-2022

* New setting `xliffSync.useSelfClosingTags` that can be used to specify whether to use self-closing tags in the XLIFF target translation files. (GitHub issue [#97](https://github.com/rvanbekkum/vsc-xliff-sync/issues/97))
Expand Down
193 changes: 152 additions & 41 deletions README.md

Large diffs are not rendered by default.

44 changes: 34 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "xliff-sync",
"displayName": "XLIFF Sync",
"description": "A tool to keep XLIFF translation files in sync.",
"version": "1.4.0",
"version": "1.5.3",
"publisher": "rvanbekkum",
"repository": {
"type": "git",
Expand All @@ -25,21 +25,13 @@
"theme": "dark"
},
"engines": {
"vscode": "^1.47.0"
"vscode": "^1.75.0"
},
"categories": [
"Other"
],
"main": "./out/extension",
"activationEvents": [
"onCommand:xliffSync.checkForMissingTranslations",
"onCommand:xliffSync.checkForNeedWorkTranslations",
"onCommand:xliffSync.createNewTargetFiles",
"onCommand:xliffSync.findNextMissingTarget",
"onCommand:xliffSync.findNextNeedsWorkTarget",
"onCommand:xliffSync.importTranslationsFromFiles",
"onCommand:xliffSync.synchronizeFile",
"onCommand:xliffSync.synchronizeSources",
"workspaceContains:**/*.xlf",
"workspaceContains:**/*.xlf2"
],
Expand Down Expand Up @@ -383,6 +375,28 @@
"default": "TargetLanguageCode",
"description": "Specifies which target language to use by default in the XLIFF Sync snippets.",
"scope": "resource"
},
"xliffSync.defaultLanguages": {
"type": "array",
"items": {
"type": "string"
},
"examples": [
"en-US",
"de-DE"
],
"default": [],
"uniqueItems": true,
"description": "Specifies the languages that should automatically be used for the translation file generation. \nExamples: \"en-US\", \"de-DE\".",
"order": 0,
"scope": "resource"
},
"xliffSync.buildCommandToExecute": {
"type": "string",
"default": "al.package",
"description": "Specifies the build command to execute when building with translations.",
"order": 1,
"scope": "resource"
}
}
},
Expand Down Expand Up @@ -426,6 +440,11 @@
"command": "xliffSync.importTranslationsFromFiles",
"title": "Import Translations from File(s)",
"category": "XLIFF"
},
{
"command": "xliffSync.buildWithTranslations",
"title": "Build with Translations",
"category": "XLIFF"
}
],
"keybindings": [
Expand All @@ -446,6 +465,11 @@
"command": "xliffSync.findNextNeedsWorkTarget",
"key": "alt+x w",
"when": "resourceExtname == .xlf"
},
{
"command": "xliffSync.buildWithTranslations",
"key": "ctrl+shift+t",
"when": "workspaceFolderCount > 0"
}
],
"menus": {
Expand Down
Binary file added resources/alParseFromDevNoteSnippet.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified resources/xliffSync_commandPaletteCommands.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/xliffSync_defaultLanguages.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from 'vscode';

import { registerSnippets } from './features/snippets';
import { synchronizeFiles, synchronizeWithSelectedFile, createNewTargetFiles } from './features/trans-sync';
import { synchronizeFiles, synchronizeWithSelectedFile, createNewTargetFiles, buildWithTranslations } from './features/trans-sync';
import { XliffTranslationChecker } from './features/trans-check';
import { XliffTranslationImport } from './features/trans-import';

Expand All @@ -13,7 +13,7 @@ export function activate(context: ExtensionContext) {
new XliffTranslationImport(context);

context.subscriptions.push(
commands.registerCommand('xliffSync.createNewTargetFiles', async() => {
commands.registerCommand('xliffSync.createNewTargetFiles', async () => {
createNewTargetFiles();
})
);
Expand All @@ -35,6 +35,12 @@ export function activate(context: ExtensionContext) {
})
);

context.subscriptions.push(
commands.registerCommand('xliffSync.buildWithTranslations', async () => {
buildWithTranslations();
})
);

registerSnippets();
}

Expand Down
44 changes: 31 additions & 13 deletions src/features/tools/files-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,48 @@ export class FilesHelper {
let uris: Uri[] = [];

if (fileType) {
uris = (await FilesHelper.findTranslationFiles(fileType, workspaceFolder)) || [];
uris = (await FilesHelper.findTranslationFiles(fileType, workspaceFolder)) || [];
}

if (!uris.length) {
fileType = await window.showQuickPick(['xlf', 'xlf2'], {
placeHolder: 'Translation file type',
});
fileType = await window.showQuickPick(['xlf', 'xlf2'], {
placeHolder: 'Translation file type',
});

if (fileType) {
uris = (await FilesHelper.findTranslationFiles(fileType, workspaceFolder)) || [];
if (fileType) {
uris = (await FilesHelper.findTranslationFiles(fileType, workspaceFolder)) || [];

if (uris.length) {
workspace.getConfiguration('xliffSync', workspaceFolder?.uri).update('fileType', fileType);
}
if (uris.length) {
workspace.getConfiguration('xliffSync', workspaceFolder?.uri).update('fileType', fileType);
}
}
}

if (!uris.length) {
throw new Error(`No translation file found (Workspace: "${workspaceFolder?.name}").`);
throw new Error(`No translation file found (Workspace: "${workspaceFolder?.name}").`);
}

return uris;
}

/**
* Checks if translation files exist in the opened workspace
*
* @param {WorkspaceFolder} workspaceFolder The folder to restrict the search to.
*
* @returns A boolean that specifies whether translation files exist in the current workspace.
*/
public static async xliffFilesExist(workspaceFolder?: WorkspaceFolder): Promise<boolean> {
let fileType: string | undefined = workspace.getConfiguration('xliffSync', workspaceFolder?.uri)['fileType'];
let uris: Uri[] = [];

if (fileType) {
uris = (await FilesHelper.findTranslationFiles(fileType, workspaceFolder)) || [];
}

return uris.length !== 0;
}

/**
* Retrieves the base/source/generated XLIFF file from a collection of XLIFF file URIs.
* Also prompts the user to specify a base file, if this wasn't done already.
Expand Down Expand Up @@ -114,11 +132,11 @@ export class FilesHelper {
if (xliffUris.length > 1) {
const fsPaths = xliffUris.map((uri) => uri.fsPath);
const sourcePath = await window.showQuickPick(fsPaths, {
placeHolder: 'Select the base XLIFF file',
placeHolder: 'Select the base XLIFF file',
});

if (!sourcePath) {
return undefined;
return undefined;
}

sourceUri = xliffUris.find((uri) => uri.fsPath === sourcePath)!;
Expand Down Expand Up @@ -168,7 +186,7 @@ export class FilesHelper {
}

public static getTranslationFileExtensions(fileType: string): string {
switch(fileType) {
switch (fileType) {
case 'xlf':
return 'xlf';
case 'xlf2':
Expand Down
2 changes: 1 addition & 1 deletion src/features/trans-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ function checkForOptionMemberLeadingSpacesMismatch(sourceText: string, translati
return false;
}

function getConsecutiveSpacesMatchesFromText(textToCheck: string): RegExpMatchArray {
function getConsecutiveSpacesMatchesFromText(textToCheck: string): RegExpMatchArray | [] {
return (textToCheck.match(/\s\s+/g) || []);
}

Expand Down
54 changes: 45 additions & 9 deletions src/features/trans-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import {
window,
workspace,
WorkspaceConfiguration,
WorkspaceFolder
WorkspaceFolder,
commands
} from 'vscode';

import { FilesHelper, LanguageHelper, WorkspaceHelper } from './tools';
Expand Down Expand Up @@ -73,10 +74,16 @@ export async function createNewTargetFiles() {

let uris: Uri[] = await FilesHelper.getXliffFileUris(workspaceFolder);
let sourceUri: Uri = await FilesHelper.getXliffSourceFile(uris, workspaceFolder);
await executeCreateNewTargetFiles(workspaceFolder, sourceUri);
}

async function executeCreateNewTargetFiles(workspaceFolder: WorkspaceFolder | undefined, sourceUri: Uri) {
const fileType: string | undefined = workspace.getConfiguration('xliffSync', workspaceFolder?.uri)['fileType'];
const targetLanguages: string[] | undefined = await selectNewTargetLanguages(fileType!, true);
if (!targetLanguages) {
let targetLanguages: string[] | undefined = workspace.getConfiguration('xliffSync', workspaceFolder?.uri)['defaultLanguages'];
if (!targetLanguages || targetLanguages.length === 0) {
targetLanguages = await selectNewTargetLanguages(fileType!, true);
}
if (!targetLanguages || targetLanguages.length === 0) {
return;
}

Expand All @@ -85,6 +92,35 @@ export async function createNewTargetFiles() {
}
}

export async function buildWithTranslations() {
return await window.withProgress({
location: ProgressLocation.Notification,
title: `Building with Translations`,
cancellable: false
}, async progress => {
progress.report({ message: "Initializing..." });
let workspaceFolders: WorkspaceFolder[] | undefined = await WorkspaceHelper.getWorkspaceFolders(false);
let workspaceFolder: WorkspaceFolder | undefined = workspaceFolders?.[0];
if (!workspaceFolder) {
throw new Error(`No workspace found for active file.`);
}

// Execute the build command (Ctrl + Shift + B)
progress.report({ message: "Executing build command..." });
const buildCommand: string | undefined = workspace.getConfiguration('xliffSync', workspaceFolder.uri)['buildCommandToExecute'];
if (!buildCommand) {
throw new Error(`No build command specified`);
}
await commands.executeCommand(buildCommand);

// Execute the xliffSync.synchronizeSources command
progress.report({ message: "Synchronizing Translation Units..." });
await synchronizeFilesInWorkspace(true, workspaceFolder);

progress.report({ message: "Build and translation synchronization complete!" });
});
}

/**
* Synchronize translation files in a workspace.
*
Expand Down Expand Up @@ -188,9 +224,9 @@ async function selectNewTargetLanguages(fileType: string, multiSelectAllowed: bo
var enterCustomLabel = '$(pencil) Enter custom...';
var altActions = [];
if (multiSelectAllowed) {
altActions.push({label: multiSelectLabel});
altActions.push({ label: multiSelectLabel });
}
altActions.push({label: enterCustomLabel});
altActions.push({ label: enterCustomLabel });

const targetLanguagePickSingle: QuickPickItem | undefined = await window.showQuickPick<QuickPickItem>(
altActions.concat(languageTagOptions),
Expand All @@ -203,7 +239,7 @@ async function selectNewTargetLanguages(fileType: string, multiSelectAllowed: bo
return undefined;
}
if (targetLanguagePickSingle.label === enterCustomLabel) {
var customTargetLanguage = await window.showInputBox({prompt: 'Enter target language tag', placeHolder: 'Example: en-US'});
var customTargetLanguage = await window.showInputBox({ prompt: 'Enter target language tag', placeHolder: 'Example: en-US' });
if (!customTargetLanguage) {
return undefined;
}
Expand Down Expand Up @@ -258,7 +294,7 @@ async function synchronizeTargetFile(sourceUri: Uri, targetUri: Uri | undefined,
const newFileContents = await XlfTranslator.synchronize(source, target, targetLanguage, workspaceFolder);

if (!newFileContents) {
throw new Error(`No ouput generated.`);
throw new Error(`No output generated.`);
}

targetUri = await FilesHelper.createNewTargetFile(targetUri, newFileContents, sourceUri, targetLanguage);
Expand All @@ -283,7 +319,7 @@ async function synchronizeAllFiles(sourceUri: Uri, targetUris: Uri[], workspaceF
equivalentLanguages = xliffWorkspaceConfiguration['equivalentLanguages'];
}
const equivalentLanguagesEnabled: boolean = xliffWorkspaceConfiguration['equivalentLanguagesEnabled'];
let slavesToMaster: {[id: string]: string} = {};
let slavesToMaster: { [id: string]: string } = {};
if (equivalentLanguagesEnabled) {
for (let master in equivalentLanguages) {
const slavePattern = equivalentLanguages[master];
Expand Down Expand Up @@ -362,7 +398,7 @@ async function synchronizeAllFiles(sourceUri: Uri, targetUris: Uri[], workspaceF
await autoRunTranslationChecks(workspaceFolder);
}

function getMasterLanguage(slavePatternsToMaster: {[id: string]: string}, targetLanguage: string): string | undefined {
function getMasterLanguage(slavePatternsToMaster: { [id: string]: string }, targetLanguage: string): string | undefined {
for (let slavePattern in slavePatternsToMaster) {
if (new RegExp(slavePattern).test(targetLanguage)) {
return slavePatternsToMaster[slavePattern];
Expand Down

0 comments on commit 6d7a2f4

Please sign in to comment.