diff --git a/README.md b/README.md index b95c97f..8cbddb1 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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. diff --git a/package-lock.json b/package-lock.json index a111738..372ef97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { "name": "commit-translator", - "version": "0.0.1", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "commit-translator", - "version": "0.0.1", + "version": "1.0.0", + "license": "MIT", "dependencies": { "axios": "^1.6.2", "lodash": "^4.17.21", @@ -16,7 +17,7 @@ "@types/lodash": "^4.14.202", "@types/mocha": "^10.0.3", "@types/node": "18.x", - "@types/vscode": "^1.84.0", + "@types/vscode": "^1.83.1", "@typescript-eslint/eslint-plugin": "^6.9.0", "@typescript-eslint/parser": "^6.9.0", "@vscode/test-electron": "^2.3.6", diff --git a/package.json b/package.json index 3168e70..27ae00b 100644 --- a/package.json +++ b/package.json @@ -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" @@ -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" } } } diff --git a/src/api/postDeeplApi.ts b/src/api/postDeeplApi.ts index b7bd9ee..1b33f1b 100644 --- a/src/api/postDeeplApi.ts +++ b/src/api/postDeeplApi.ts @@ -12,13 +12,15 @@ type TranslatedDataResponse = { export const postDeeplApi = async ({ text, apiKey, + targetLanguage, }: { text: string; apiKey: string; + targetLanguage: string; }): Promise => { 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; diff --git a/src/commands/setApiKey.ts b/src/commands/setApiKey.ts index b919510..873f91c 100644 --- a/src/commands/setApiKey.ts +++ b/src/commands/setApiKey.ts @@ -1,6 +1,6 @@ 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() { @@ -8,7 +8,7 @@ export async function setApiKeyCommand() { title: "Please enter your API Key", }); - if (!validateString(apiKey)) { + if (!isStringValid(apiKey)) { vscode.window.showErrorMessage("api key should be string type"); return; } diff --git a/src/commands/translateCommit.ts b/src/commands/translateCommit.ts index b4c2d94..14640a9 100644 --- a/src/commands/translateCommit.ts +++ b/src/commands/translateCommit.ts @@ -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("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; } diff --git a/src/types/configuration.ts b/src/types/configuration.ts index c8b09e8..be2a5bc 100644 --- a/src/types/configuration.ts +++ b/src/types/configuration.ts @@ -3,6 +3,7 @@ import { z } from "zod"; export const configurationSchema = z.object({ deepl: z.object({ apiKey: z.string().optional(), + targetLanguage: z.string().optional(), }), }); diff --git a/src/utils/apiKey.ts b/src/utils/apiKey.ts deleted file mode 100644 index efdcd13..0000000 --- a/src/utils/apiKey.ts +++ /dev/null @@ -1,14 +0,0 @@ -import getParsedConfiguration from "./getParsedConfiguration"; -import validateString from "./validateString"; - -export function getApiKey() { - const { - deepl: { apiKey }, - } = getParsedConfiguration(); - return apiKey; -} - -export function isValidateApiKey() { - const apiKey = getApiKey(); - return validateString(apiKey); -} diff --git a/src/utils/getConfiguration.ts b/src/utils/configuration/getConfiguration.ts similarity index 69% rename from src/utils/getConfiguration.ts rename to src/utils/configuration/getConfiguration.ts index ec1cf07..7568cd9 100644 --- a/src/utils/getConfiguration.ts +++ b/src/utils/configuration/getConfiguration.ts @@ -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); diff --git a/src/utils/setConfiguration.ts b/src/utils/configuration/setConfiguration.ts similarity index 100% rename from src/utils/setConfiguration.ts rename to src/utils/configuration/setConfiguration.ts diff --git a/src/utils/getDeepLApiKey.ts b/src/utils/getDeepLApiKey.ts index 1fa41b8..6bdf673 100644 --- a/src/utils/getDeepLApiKey.ts +++ b/src/utils/getDeepLApiKey.ts @@ -1,9 +1,7 @@ -import * as vscode from "vscode"; - -export function getDeepLApiKey() { - const apiKey = vscode.workspace - .getConfiguration("commit-translator.deepl") - .get("apiKey"); +import { ApiKey } from "../constants/api"; +import { getConfiguration } from "./configuration/getConfiguration"; +export default function getDeepLApiKey(): string | undefined { + const apiKey = getConfiguration().get(ApiKey); return apiKey; } diff --git a/src/utils/getParsedConfiguration.ts b/src/utils/getParsedConfiguration.ts deleted file mode 100644 index 1b5de30..0000000 --- a/src/utils/getParsedConfiguration.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { configurationSchema } from "../types/configuration"; -import { getConfiguration } from "./getConfiguration"; - -export default function getParsedConfiguration() { - return configurationSchema.parse(getConfiguration()); -} diff --git a/src/utils/getTranslatedCommitMessage.ts b/src/utils/getTranslatedCommitMessage.ts index d6bfa00..7c0def5 100644 --- a/src/utils/getTranslatedCommitMessage.ts +++ b/src/utils/getTranslatedCommitMessage.ts @@ -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 { try { - const response = await postDeeplApi({ text: commit, apiKey: apikey }); + const targetLanguage = + getConfiguration().get("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) { diff --git a/src/utils/git/activateGitExtension.ts b/src/utils/git/activateGitExtension.ts new file mode 100644 index 0000000..6387e43 --- /dev/null +++ b/src/utils/git/activateGitExtension.ts @@ -0,0 +1,11 @@ +import * as vscode from "vscode"; +import { GitExtension } from "../../types/vscode"; + +export async function activateGitExtension(gitExtension: vscode.Extension) { + if (!gitExtension.isActive) { + await gitExtension.activate(); + } + if (!gitExtension.isActive) { + throw new Error("Git extension is not active"); + } +} diff --git a/src/utils/git/getGitExtension.ts b/src/utils/git/getGitExtension.ts new file mode 100644 index 0000000..d14ba1b --- /dev/null +++ b/src/utils/git/getGitExtension.ts @@ -0,0 +1,6 @@ +import * as vscode from "vscode"; +import { GitExtension } from "../../types/vscode"; + +export default function getGitExtension() { + return vscode.extensions.getExtension("vscode.git"); +} diff --git a/src/utils/git/getSingleRepository.ts b/src/utils/git/getSingleRepository.ts new file mode 100644 index 0000000..3e38b26 --- /dev/null +++ b/src/utils/git/getSingleRepository.ts @@ -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): Repository { + const repositories = gitExtension.exports.getAPI(1).repositories; + + if (isEmpty(repositories)) { + throw new Error("No repositories found"); + } + return repositories[0]; +} diff --git a/src/utils/git/index.ts b/src/utils/git/index.ts new file mode 100644 index 0000000..282a24f --- /dev/null +++ b/src/utils/git/index.ts @@ -0,0 +1,4 @@ +export * from "./activateGitExtension"; +export * from "./getSingleRepository"; +export * from "./isGitExtensionValid"; +export * from "./getGitExtension"; diff --git a/src/utils/git/isGitExtensionValid.ts b/src/utils/git/isGitExtensionValid.ts new file mode 100644 index 0000000..ae607be --- /dev/null +++ b/src/utils/git/isGitExtensionValid.ts @@ -0,0 +1,12 @@ +import * as vscode from "vscode"; +import { GitExtension } from "../../types/vscode"; + +export function isGitExtensionValid( + gitExtension: vscode.Extension | undefined +): gitExtension is vscode.Extension { + if (!gitExtension) { + vscode.window.showErrorMessage("Git extension is not installed."); + return false; + } + return true; +} diff --git a/src/utils/gitExtension.ts b/src/utils/gitExtension.ts deleted file mode 100644 index b964e5f..0000000 --- a/src/utils/gitExtension.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as vscode from "vscode"; -import { GitExtension, Repository } from "../types/vscode"; -import { isEmpty } from "lodash"; - -export function isGitExtensionValidate( - gitExtension: vscode.Extension | undefined -): gitExtension is vscode.Extension { - if (!gitExtension) { - vscode.window.showErrorMessage("Git extension is not installed."); - return false; - } - return true; -} - -export async function activateGitExtension(gitExtension: vscode.Extension) { - if (!gitExtension.isActive) { - await gitExtension.activate(); - } - if (!gitExtension.isActive) { - throw new Error("Git extension is not active"); - } -} - -export function getSingleRepository(gitExtension: vscode.Extension): Repository { - const repositories = gitExtension.exports.getAPI(1).repositories; - - if (isEmpty(repositories)) { - throw new Error("No repositories found"); - } - return repositories[0]; -} diff --git a/src/utils/isStringValid.ts b/src/utils/isStringValid.ts new file mode 100644 index 0000000..9c6c621 --- /dev/null +++ b/src/utils/isStringValid.ts @@ -0,0 +1,5 @@ +import { isEmpty } from "lodash"; + +export default function isStringValid(text: string | null | undefined): text is string { + return Boolean(text) && !isEmpty(text); +} diff --git a/src/utils/validateString.ts b/src/utils/validateString.ts deleted file mode 100644 index 4585d59..0000000 --- a/src/utils/validateString.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { isEmpty } from "lodash"; - -export default function validateString(text: string | null | undefined): text is string { - return Boolean(text) && !isEmpty(text); -} diff --git a/yarn.lock b/yarn.lock index 33653c3..cc9c387 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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==