Skip to content

Commit

Permalink
Multilingual translation support (#5)
Browse files Browse the repository at this point in the history
* fix: Error handling when API KEY is empty

* feat: Multi-language support

* docs: update README.md
  • Loading branch information
nim-od authored Dec 3, 2023
1 parent 8dea892 commit 0313955
Show file tree
Hide file tree
Showing 22 changed files with 112 additions and 114 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
[![VS Code extension installs](https://img.shields.io/visual-studio-marketplace/i/nimod7890.commit-translator)](https://marketplace.visualstudio.com/items?itemName=nimod7890.commit-translator)
[![VS Code extension rating](https://img.shields.io/visual-studio-marketplace/r/nimod7890.commit-translator)](https://marketplace.visualstudio.com/items?itemName=nimod7890.commit-translator)

Welcome to Commit Message Translator for Visual Studio Code! This extension leverages the power of the DeepL Translate API to seamlessly translate your commit messages from Korean to English. Ideal for international teams and open-source projects where English is the primary language of communication.

## Preview

![preview](assets/images/preview.gif)

## Key Features

- **Korean to English Translation**: Automatically translate your commit messages from Korean to English.
- **MultiLanguage Translation**: Translate your commit messages.(default: EN)
- **Easy to Use**: A simple and intuitive interface integrated right into VSCode.
- **DeepL API Integration**: Powered by the reliable and accurate DeepL Translate API.

Expand All @@ -24,7 +22,7 @@ Welcome to Commit Message Translator for Visual Studio Code! This extension leve
## Usage

1. **Write Your Commit Message**: Simply write your commit message in Korean as you normally would.
2. **Translate**: Click the 'Translate' button in the GitHub extension menu.
2. **Translate**: Click the commit-translator icon button in the source control menu.
3. **Enter API Key**: If you haven't already set up a DeepL API key, you will be prompted to enter it. This is required for the translation service.
1. Go to the [DeepL Page](https://www.deepl.com/pro#developer).
4. **Commit**: Your commit message will be translated to English. Review and commit as usual.
Expand Down
7 changes: 4 additions & 3 deletions package-lock.json

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

9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "commit-translator",
"displayName": "Commit Message Translator",
"description": "VSCode extension which translates commit message ",
"version": "1.0.0",
"version": "1.1.0",
"repository": {
"type": "git",
"url": "https://github.com/nimod7890/commit-translator"
Expand Down Expand Up @@ -62,7 +62,12 @@
"commit-translator.deepl.apiKey": {
"type": "string",
"default": "",
"description": "Needed for translating commit message."
"description": "deepl auth key for translating commit message."
},
"commit-translator.deepl.targetLanguage": {
"type": "string",
"default": "EN",
"description": "Enter the language code for your target translation language. \nex) 'KO' for Korean.\nmore: https://www.deepl.com/docs-api/translate-text"
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/api/postDeeplApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ type TranslatedDataResponse = {
export const postDeeplApi = async ({
text,
apiKey,
targetLanguage,
}: {
text: string;
apiKey: string;
targetLanguage: string;
}): Promise<TranslatedDataResponse> => {
const { data } = await client.post(
`/v2/translate`,
{ text: [text], target_lang: "EN" },
{ text: [text], target_lang: targetLanguage },
{ headers: { Authorization: `DeepL-Auth-Key ${apiKey}` } }
);
return data;
Expand Down
6 changes: 3 additions & 3 deletions src/commands/setApiKey.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as vscode from "vscode";
import { setConfigurationValue } from "../utils/setConfiguration";
import validateString from "../utils/validateString";
import isStringValid from "../utils/isStringValid";
import { setConfigurationValue } from "../utils/configuration/setConfiguration";
import { ApiKey } from "../constants/api";

export async function setApiKeyCommand() {
const apiKey = await vscode.window.showInputBox({
title: "Please enter your API Key",
});

if (!validateString(apiKey)) {
if (!isStringValid(apiKey)) {
vscode.window.showErrorMessage("api key should be string type");
return;
}
Expand Down
54 changes: 22 additions & 32 deletions src/commands/translateCommit.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,46 @@
import { isEmpty } from "lodash";
import * as vscode from "vscode";
import { setApiKeyCommand } from ".";
import { GitExtension } from "../types/vscode";

import { getDeepLApiKey } from "../utils/getDeepLApiKey";
import { getTranslatedCommitMessage } from "../utils/getTranslatedCommitMessage";
import {
activateGitExtension,
getSingleRepository,
isGitExtensionValidate,
} from "../utils/gitExtension";
import validateString from "../utils/validateString";
import { isGitExtensionValid, activateGitExtension, getSingleRepository } from "../utils/git";
import getTranslatedCommitMessage from "../utils/getTranslatedCommitMessage";
import getDeepLApiKey from "../utils/getDeepLApiKey";
import isStringValid from "../utils/isStringValid";
import { isEmpty } from "lodash";
import getGitExtension from "../utils/git/getGitExtension";

export async function translateCommitCommand() {
/** 1. (success) check if git extension is valid */
const gitExtension =
vscode.extensions.getExtension<GitExtension>("vscode.git");
if (!isGitExtensionValidate(gitExtension)) {
/** 1. check if git extension is valid & activate git extension*/
const gitExtension = getGitExtension();
if (!isGitExtensionValid(gitExtension)) {
return;
}
await activateGitExtension(gitExtension);

/** 2. (success ?) check if apiKey is valid */
let apikey: string | undefined = getDeepLApiKey();
if (!validateString(apikey)) {
apikey = await setApiKeyCommand();
// vscode.window.showInformationMessage(apikey as string);
// await vscode.commands.executeCommand(Commands.SetApiKey);
/** 2. check if apiKey exists*/
let apiKey = getDeepLApiKey();
if (!isStringValid(apiKey)) {
apiKey = await setApiKeyCommand();
}

// if (!isValidateApiKey()) {
// vscode.window.showInformationMessage("api key is invalid");
// return;
// vscode.window.showInformationMessage(apikey as string);
// await vscode.commands.executeCommand(Commands.SetApiKey);
// }
if (!isStringValid(apiKey)) {
return;
}

/** 3. (success) get repository from git */
/** 3. get repository from git */
const repository = getSingleRepository(gitExtension);

/** 4. (success) get commit from repository */
/** 4. get commit from repository */
const commit = repository.inputBox.value;
if (isEmpty(commit)) {
vscode.window.showErrorMessage("Commit message is empty");
return;
}
/** 5. (success) translate commit message with Deepl api */

/** 5. translate commit message with Deepl api */
const translatedMessage = await getTranslatedCommitMessage({
apikey: apikey as string,
commit,
apiKey,
});

/** 6. (success) log translated commit */
/** 6. log translated commit */
repository.inputBox.value = translatedMessage;
}
1 change: 1 addition & 0 deletions src/types/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { z } from "zod";
export const configurationSchema = z.object({
deepl: z.object({
apiKey: z.string().optional(),
targetLanguage: z.string().optional(),
}),
});

Expand Down
14 changes: 0 additions & 14 deletions src/utils/apiKey.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as vscode from "vscode";
import { WorkspaceKey } from "../constants/workspace";
import { WorkspaceKey } from "../../constants/workspace";

export function getConfiguration() {
return vscode.workspace.getConfiguration(WorkspaceKey);
Expand Down
File renamed without changes.
10 changes: 4 additions & 6 deletions src/utils/getDeepLApiKey.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import * as vscode from "vscode";

export function getDeepLApiKey() {
const apiKey = vscode.workspace
.getConfiguration("commit-translator.deepl")
.get<string>("apiKey");
import { ApiKey } from "../constants/api";
import { getConfiguration } from "./configuration/getConfiguration";

export default function getDeepLApiKey(): string | undefined {
const apiKey = getConfiguration().get<string | undefined>(ApiKey);
return apiKey;
}
6 changes: 0 additions & 6 deletions src/utils/getParsedConfiguration.ts

This file was deleted.

19 changes: 14 additions & 5 deletions src/utils/getTranslatedCommitMessage.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import { postDeeplApi } from "../api/postDeeplApi";
import * as vscode from "vscode";
import { postDeeplApi } from "../api/postDeeplApi";
import { getConfiguration } from "./configuration/getConfiguration";

type getTranslatedCommitMessageProps = {
commit: string;
apikey: string;
apiKey: string;
};

export async function getTranslatedCommitMessage({
export default async function getTranslatedCommitMessage({
commit,
apikey,
apiKey,
}: getTranslatedCommitMessageProps): Promise<string> {
try {
const response = await postDeeplApi({ text: commit, apiKey: apikey });
const targetLanguage =
getConfiguration().get<string | undefined>("deepl.targetLanguage") ?? "EN";

const response = await postDeeplApi({
text: commit.trim(),
apiKey: apiKey,
targetLanguage: targetLanguage.trim(),
});
return response.translations[0].text;
} catch (error) {
if (error instanceof Error) {
Expand Down
11 changes: 11 additions & 0 deletions src/utils/git/activateGitExtension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as vscode from "vscode";
import { GitExtension } from "../../types/vscode";

export async function activateGitExtension(gitExtension: vscode.Extension<GitExtension>) {
if (!gitExtension.isActive) {
await gitExtension.activate();
}
if (!gitExtension.isActive) {
throw new Error("Git extension is not active");
}
}
6 changes: 6 additions & 0 deletions src/utils/git/getGitExtension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as vscode from "vscode";
import { GitExtension } from "../../types/vscode";

export default function getGitExtension() {
return vscode.extensions.getExtension<GitExtension>("vscode.git");
}
12 changes: 12 additions & 0 deletions src/utils/git/getSingleRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as vscode from "vscode";
import { isEmpty } from "lodash";
import { GitExtension, Repository } from "../../types/vscode";

export function getSingleRepository(gitExtension: vscode.Extension<GitExtension>): Repository {
const repositories = gitExtension.exports.getAPI(1).repositories;

if (isEmpty(repositories)) {
throw new Error("No repositories found");
}
return repositories[0];
}
4 changes: 4 additions & 0 deletions src/utils/git/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./activateGitExtension";
export * from "./getSingleRepository";
export * from "./isGitExtensionValid";
export * from "./getGitExtension";
12 changes: 12 additions & 0 deletions src/utils/git/isGitExtensionValid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as vscode from "vscode";
import { GitExtension } from "../../types/vscode";

export function isGitExtensionValid(
gitExtension: vscode.Extension<GitExtension> | undefined
): gitExtension is vscode.Extension<GitExtension> {
if (!gitExtension) {
vscode.window.showErrorMessage("Git extension is not installed.");
return false;
}
return true;
}
31 changes: 0 additions & 31 deletions src/utils/gitExtension.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/utils/isStringValid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { isEmpty } from "lodash";

export default function isStringValid(text: string | null | undefined): text is string {
return Boolean(text) && !isEmpty(text);
}
5 changes: 0 additions & 5 deletions src/utils/validateString.ts

This file was deleted.

2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz"
integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==

"@types/vscode@^1.84.0":
"@types/vscode@^1.83.1":
version "1.84.2"
resolved "https://registry.npmjs.org/@types/vscode/-/vscode-1.84.2.tgz"
integrity sha512-LCe1FvCDMJKkPdLVGYhP0HRJ1PDop2gRVm/zFHiOKwYLBRS7vEV3uOOUId4HMV+L1IxqyS+IZXMmlSMRbZGIAw==
Expand Down

0 comments on commit 0313955

Please sign in to comment.