From 44fe48e6738b0dfd57f014bf7c4ac789134fdccb Mon Sep 17 00:00:00 2001 From: Chris Johnston Date: Fri, 21 Aug 2020 21:26:00 +0100 Subject: [PATCH 1/3] feat: Added translations --- package.json | 108 +++++++++++++++++++++---------------------- package.nls.json | 49 ++++++++++++++++++++ src/extension.ts | 6 ++- src/localise.ts | 117 +++++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 5 ++ 5 files changed, 229 insertions(+), 56 deletions(-) create mode 100644 package.nls.json create mode 100644 src/localise.ts diff --git a/package.json b/package.json index 8be25a836..f7c9c822f 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "commands": [ { "command": "svn.add", - "title": "Add", + "title": "%svn.command.add%", "category": "SVN", "icon": { "light": "icons/light/add.svg", @@ -141,23 +141,23 @@ }, { "command": "svn.addToIgnoreExplorer", - "title": "Ignore file/ext from SVN (svn:ignore)", + "title": "%svn.command.addToIgnore%", "category": "SVN" }, { "command": "svn.addToIgnoreSCM", - "title": "Ignore file/ext from SVN (svn:ignore)", + "title": "%svn.command.addToIgnore%", "category": "SVN" }, { "command": "svn.branchchanges.openDiff", "category": "SVN", - "title": "Open diff" + "title": "%svn.command.openDiff%" }, { "command": "svn.branchchanges.refresh", "category": "SVN", - "title": "Refresh branch changes", + "title": "%svn.command.refreshBranchChanges%", "icon": { "dark": "icons/dark/refresh.svg", "light": "icons/light/refresh.svg" @@ -165,7 +165,7 @@ }, { "command": "svn.changelist", - "title": "Set changelist", + "title": "%svn.command.setChangelist%", "category": "SVN", "icon": { "light": "icons/light/changelist.svg", @@ -174,22 +174,22 @@ }, { "command": "svn.checkout", - "title": "Checkout", + "title": "%svn.command.checkout%", "category": "SVN" }, { "command": "svn.cleanup", - "title": "Clean up working copy", + "title": "%svn.command.cleanWorkingCopy%", "category": "SVN" }, { "command": "svn.close", - "title": "Close repository", + "title": "%svn.command.closeRepository%", "category": "SVN" }, { "command": "svn.commit", - "title": "Commit Selected", + "title": "%svn.command.commitSelected%", "category": "SVN", "icon": { "light": "icons/light/check.svg", @@ -198,7 +198,7 @@ }, { "command": "svn.commitWithMessage", - "title": "Commit Changes", + "title": "%svn.command.commitChanges%", "category": "SVN", "icon": { "light": "icons/light/check.svg", @@ -207,38 +207,38 @@ }, { "command": "svn.deleteUnversioned", - "title": "Delete selected files", + "title": "%svn.command.deleteSelectedFiles%", "category": "SVN" }, { "command": "svn.itemlog.copymsg", "category": "SVN", - "title": "Copy message" + "title": "%svn.command.copyMessage%" }, { "command": "svn.itemlog.copyrevision", "category": "SVN", - "title": "Copy revision number" + "title": "%svn.command.copyRevisionNumber%" }, { "command": "svn.itemlog.openDiff", - "title": "Open diff", + "title": "%svn.command.openDiff%", "category": "SVN" }, { "command": "svn.itemlog.openDiffBase", - "title": "Open diff with BASE", + "title": "%svn.command.openDiffBase%", "category": "SVN" }, { "command": "svn.itemlog.openFileRemote", - "title": "Open this revision", + "title": "%svn.command.openThisRevision%", "category": "SVN" }, { "command": "svn.itemlog.refresh", "category": "SVN", - "title": "Refresh log for item", + "title": "%svn.command.refreshLogForItem%", "icon": { "dark": "icons/dark/refresh.svg", "light": "icons/light/refresh.svg" @@ -246,12 +246,12 @@ }, { "command": "svn.log", - "title": "Show commit messages", + "title": "%svn.command.showCommitMessages%", "category": "SVN" }, { "command": "svn.openChangeBase", - "title": "Open Changes with BASE", + "title": "%svn.command.openChangesBase%", "category": "SVN", "icon": { "light": "icons/light/open-change-base.svg", @@ -260,7 +260,7 @@ }, { "command": "svn.openChangeHead", - "title": "Open Changes with HEAD", + "title": "%svn.command.openChangesHead%", "category": "SVN", "icon": { "light": "icons/light/open-change-head.svg", @@ -269,12 +269,12 @@ }, { "command": "svn.openChangePrev", - "title": "Open Changes with PREV", + "title": "%svn.command.openChangesPrev%", "category": "SVN" }, { "command": "svn.openFile", - "title": "Open File", + "title": "%svn.command.openFile%", "category": "SVN", "icon": { "light": "icons/light/open-file.svg", @@ -283,27 +283,27 @@ }, { "command": "svn.openHEADFile", - "title": "Open File (HEAD)", + "title": "%svn.command.openFileHead%", "category": "SVN" }, { "command": "svn.patch", - "title": "Show diff patch for selected", + "title": "%svn.command.showPatchSelected%", "category": "SVN" }, { "command": "svn.patchAll", - "title": "Show all diff patch", + "title": "%svn.command.showPatchAll%", "category": "SVN" }, { "command": "svn.patchChangeList", - "title": "Show patch from changelist", + "title": "%svn.command.showPatchChangelist%", "category": "SVN" }, { "command": "svn.pickCommitMessage", - "title": "Pick a previous commit message", + "title": "%svn.command.pickPreviousCommitMessage%", "category": "SVN", "icon": { "light": "icons/light/icon-history.svg", @@ -312,7 +312,7 @@ }, { "command": "svn.refresh", - "title": "Refresh", + "title": "%svn.command.refresh%", "category": "SVN", "icon": { "light": "icons/light/refresh.svg", @@ -321,7 +321,7 @@ }, { "command": "svn.refreshRemoteChanges", - "title": "Refresh Remote Changes", + "title": "%svn.command.refreshRemoteChanges%", "category": "SVN", "icon": { "light": "icons/light/refresh.svg", @@ -330,23 +330,23 @@ }, { "command": "svn.remove", - "title": "Remove Selected", + "title": "%svn.command.removeSelected%", "category": "SVN" }, { "command": "svn.removeUnversioned", - "title": "Remove unversioned files", + "title": "%svn.command.removeUnversioned%", "category": "SVN" }, { "command": "svn.renameExplorer", - "title": "Rename with SVN", + "title": "%svn.command.rename%", "category": "SVN" }, { "command": "svn.repolog.addrepolike", "category": "SVN", - "title": "Add repo-like path", + "title": "%svn.command.addRepoPath%", "icon": { "dark": "icons/dark/add.svg", "light": "icons/light/add.svg" @@ -355,32 +355,32 @@ { "command": "svn.repolog.copymsg", "category": "SVN", - "title": "Copy message" + "title": "%svn.command.copyMessage%" }, { "command": "svn.repolog.copyrevision", "category": "SVN", - "title": "Copy revision number" + "title": "%svn.command.copyRevisionNumber%" }, { "command": "svn.repolog.openDiff", "category": "SVN", - "title": "Open diff" + "title": "%svn.command.openDiff%" }, { "command": "svn.repolog.openFileLocal", "category": "SVN", - "title": "Open WC version of a file" + "title": "%svn.command.openWcFile%" }, { "command": "svn.repolog.openFileRemote", "category": "SVN", - "title": "Open this revision" + "title": "%svn.command.openThisRevision%" }, { "command": "svn.repolog.refresh", "category": "SVN", - "title": "Refresh log", + "title": "%svn.command.refreshLog%", "icon": { "dark": "icons/dark/refresh.svg", "light": "icons/light/refresh.svg" @@ -389,11 +389,11 @@ { "command": "svn.repolog.remove", "category": "SVN", - "title": "Remove" + "title": "%svn.command.remove%" }, { "command": "svn.resolve", - "title": "Resolve conflicts for selected", + "title": "%svn.command.resolveSelected%", "category": "SVN", "icon": { "light": "icons/light/check.svg", @@ -402,12 +402,12 @@ }, { "command": "svn.resolveAll", - "title": "Resolve all conflicts", + "title": "%svn.command.resolveAll%", "category": "SVN" }, { "command": "svn.revert", - "title": "Revert Selected File", + "title": "%svn.command.revertSelected%", "category": "SVN", "icon": { "light": "icons/light/clean.svg", @@ -416,7 +416,7 @@ }, { "command": "svn.revertAll", - "title": "Revert All Changes", + "title": "%svn.command.revertAll%", "category": "SVN", "icon": { "light": "icons/light/clean.svg", @@ -425,7 +425,7 @@ }, { "command": "svn.revertChange", - "title": "Revert Change", + "title": "%svn.command.revertChange%", "category": "SVN", "icon": { "light": "icons/light/clean.svg", @@ -434,7 +434,7 @@ }, { "command": "svn.revertExplorer", - "title": "Revert with SVN", + "title": "%svn.command.revertSvn%", "category": "SVN", "icon": { "light": "icons/light/clean.svg", @@ -443,22 +443,22 @@ }, { "command": "svn.searchLogByRevision", - "title": "Search log by revision", + "title": "%svn.command.searchLogRevision%", "category": "SVN" }, { "command": "svn.searchLogByText", - "title": "Search log", + "title": "%svn.command.searchLog%", "category": "SVN" }, { "command": "svn.switchBranch", - "title": "Switch Branch", + "title": "%svn.command.switchBranch%", "category": "SVN" }, { "command": "svn.treeview.pullIncomingChange", - "title": "Update selected", + "title": "%svn.command.updateSelected%", "category": "SVN", "icon": { "light": "icons/light/download.svg", @@ -467,7 +467,7 @@ }, { "command": "svn.treeview.refreshProvider", - "title": "Refresh", + "title": "%svn.command.refresh%", "category": "SVN", "icon": { "light": "icons/light/refresh.svg", @@ -476,7 +476,7 @@ }, { "command": "svn.update", - "title": "Update", + "title": "%svn.command.update%", "category": "SVN", "icon": { "light": "icons/light/download.svg", @@ -1283,4 +1283,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.nls.json b/package.nls.json new file mode 100644 index 000000000..dc31553f7 --- /dev/null +++ b/package.nls.json @@ -0,0 +1,49 @@ +{ + "svn.description": "Integrated Subversion source control", + "svn.command.add": "Add", + "svn.command.addToIgnore": "Ignore file/ext from SVN (svn:ignore)", + "svn.command.openDiff": "Open diff", + "svn.command.refreshBranchChanges": "Refresh branch changes", + "svn.command.setChangelist": "Set changelist", + "svn.command.checkout": "Checkout", + "svn.command.cleanWorkingCopy": "Clean up working copy", + "svn.command.closeRepository": "Close repository", + "svn.command.commitSelected": "Commit Selected", + "svn.command.commitChanges": "Commit Changes", + "svn.command.deleteSelectedFiles": "Delete selected files", + "svn.command.copyMessage": "Copy message", + "svn.command.copyRevisionNumber": "Copy revision number", + "svn.command.openDiffBase": "Open diff with BASE", + "svn.command.openThisRevision": "Open this revision", + "svn.command.refreshLogForItem": "Refresh log for item", + "svn.command.showCommitMessages": "Show commit messages", + "svn.command.openChangesBase": "Open Changes with BASE", + "svn.command.openChangesHead": "Open Changes with HEAD", + "svn.command.openChangesPrev": "Open Changes with PREV", + "svn.command.openFile": "Open File", + "svn.command.openFileHead": "Open File (HEAD)", + "svn.command.showPatchSelected": "Show diff patch for selected", + "svn.command.showPatchAll": "Show all diff patch", + "svn.command.showPatchChangelist": "Show patch from changelist", + "svn.command.pickPreviousCommitMessage": "Pick a previous commit message", + "svn.command.refresh": "Refresh", + "svn.command.refreshRemoteChanges": "Refresh Remote Changes", + "svn.command.removeSelected": "Remove Selected", + "svn.command.removeUnversioned": "Remove unversioned files", + "svn.command.rename": "Rename with SVN", + "svn.command.addRepoPath": "Add repo-like path", + "svn.command.openWcFile": "Open WC version of a file", + "svn.command.refreshLog": "Refresh log", + "svn.command.remove": "Remove", + "svn.command.resolveSelected": "Resolve conflicts for selected", + "svn.command.resolveAll": "Resolve all conflicts", + "svn.command.revertSelected": "Revert Selected File", + "svn.command.revertAll": "Revert All Changes", + "svn.command.revertChange": "Revert Change", + "svn.command.revertSvn": "Revert with SVN", + "svn.command.searchLogRevision": "Search log by revision", + "svn.command.searchLog": "Search log", + "svn.command.switchBranch": "Switch Branch", + "svn.command.updateSelected": "Update selected", + "svn.command.update": "Update" +} diff --git a/src/extension.ts b/src/extension.ts index 6b7493b25..5603296bc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -25,12 +25,14 @@ import { BranchChangesProvider } from "./historyView/branchChangesProvider"; import { IsSvn19orGreater } from "./contexts/isSvn19orGreater"; import { IsSvn18orGreater } from "./contexts/isSvn18orGreater"; import { tempSvnFs } from "./temp_svn_fs"; +import { init } from "./localise"; -async function init( +async function _init( _context: ExtensionContext, outputChannel: OutputChannel, disposables: Disposable[] ) { + init(_context.extensionPath); const pathHint = configuration.get("path"); const svnFinder = new SvnFinder(); @@ -80,7 +82,7 @@ async function _activate(context: ExtensionContext, disposables: Disposable[]) { const tryInit = async () => { try { - await init(context, outputChannel, disposables); + await _init(context, outputChannel, disposables); } catch (err) { if (!/Svn installation not found/.test(err.message || "")) { throw err; diff --git a/src/localise.ts b/src/localise.ts new file mode 100644 index 000000000..85faedf07 --- /dev/null +++ b/src/localise.ts @@ -0,0 +1,117 @@ +import * as fs from "fs"; +import * as path from "path"; + +interface IConfig { + locale?: string; +} + +interface ILanguagePack { + [key: string]: string; +} + +declare const __non_webpack_require__: typeof require; + +class Localize { + private bundle: ILanguagePack = {}; + private extensionPath: string = ""; + constructor(private options: IConfig = {}) {} + /** + * translate the key + * @param key + * @param args + */ + public localize(key: string, ...args: string[]): string { + const languagePack = this.bundle; + const message: string = languagePack[key] || key; + return this.format(message, args); + } + public init(extensionPath: string) { + this.extensionPath = extensionPath; + this.bundle = this.resolveLanguagePack(); + } + private format(message: string, args: string[] = []): string { + let result: string; + if (args.length === 0) { + result = message; + } else { + result = message.replace(/\{(\d+)\}/g, (match, rest: any[]) => { + const index = rest[0]; + return typeof args[index] !== "undefined" ? args[index] : match; + }); + } + return result; + } + private resolveLanguagePack(): ILanguagePack { + const defaultResvoleLanguage = ".nls.json"; + let resolvedLanguage: string = ""; + const rootPath = this.extensionPath || process.cwd(); + const file = path.join(rootPath, "package"); + const options = this.options; + + if (!options.locale) { + resolvedLanguage = defaultResvoleLanguage; + } else { + let locale: string | null = options.locale; + while (locale) { + const candidate = ".nls." + locale + ".json"; + if (fs.existsSync(file + candidate)) { + resolvedLanguage = candidate; + break; + } else { + const index = locale.lastIndexOf("-"); + if (index > 0) { + locale = locale.substring(0, index); + } else { + resolvedLanguage = ".nls.json"; + locale = null; + } + } + } + } + + let defaultLanguageBundle = {}; + + // if not use default language + // then merger the Language pack + // just in case the resolveLanguage bundle missing the translation and fallback with default language + if (resolvedLanguage !== defaultResvoleLanguage) { + defaultLanguageBundle = __non_webpack_require__( + path.join(file + defaultResvoleLanguage) + ); + } + + const languageFilePath = path.join(file + resolvedLanguage); + + const isExistResolvedLanguage = fs.existsSync(languageFilePath); + + const ResolvedLanguageBundle = isExistResolvedLanguage + ? __non_webpack_require__(languageFilePath) + : {}; + + // merger with default language bundle + return { ...defaultLanguageBundle, ...ResolvedLanguageBundle }; + } +} + +let config: IConfig = { + locale: "en" +}; + +try { + config = Object.assign( + config, + JSON.parse((process.env as any).VSCODE_NLS_CONFIG) + ); +} catch (err) { + // +} + +const instance = new Localize(config); + +export function init(extensionPath: string): void { + return instance.init(extensionPath); +} + +export function localize(key: string, ...args: string[]): string { + return instance.localize(key, ...args); +} diff --git a/yarn.lock b/yarn.lock index 9e0d86ab0..87442b052 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7691,6 +7691,11 @@ vsce@^1.73.0: yauzl "^2.3.1" yazl "^2.2.2" +vscode-nls-i18n@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/vscode-nls-i18n/-/vscode-nls-i18n-0.2.0.tgz#d9c28725ea1c869c889663842fc51be8ba93f7d8" + integrity sha512-ZnckQO9aAitHZxrNIJT6/0Bt2Y+snNZZGixuXtL39p/1fLfIBsX65ZnXYu5Rq56yKalqYltrBVTRy3ZeRh3Lwg== + vscode-test@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-1.4.0.tgz#a56f73c1667b4d37ba6baa6765f233a19d4ffbfe" From d77652d73c6b1a9f415ab2c999d799026be2fc4c Mon Sep 17 00:00:00 2001 From: Chris Johnston Date: Sun, 23 Aug 2020 14:55:28 +0100 Subject: [PATCH 2/3] Added google translated ru and zh-cn translations --- package.nls.ru.json | 49 ++++++++++++++++++++++++++++++++++++++++++ package.nls.zh-cn.json | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 package.nls.ru.json create mode 100644 package.nls.zh-cn.json diff --git a/package.nls.ru.json b/package.nls.ru.json new file mode 100644 index 000000000..b4a33095b --- /dev/null +++ b/package.nls.ru.json @@ -0,0 +1,49 @@ +{ + "svn.description": "Интегрированный контроль версий Subversion", + "svn.command.add": "Добавить", + "svn.command.addToIgnore": "Игнорировать (svn:ignore)", + "svn.command.openDiff": "Открыть изменения", + "svn.command.refreshBranchChanges": "Обновить изменения ветви", + "svn.command.setChangelist": "Установить список изменений", + "svn.command.checkout": "Выгрузить (checkout)", + "svn.command.cleanWorkingCopy": "Очистить рабочую копию", + "svn.command.closeRepository": "Закрыть репозиторий", + "svn.command.commitSelected": "Фиксация выбрана", + "svn.command.commitChanges": "Зафиксировать изменения", + "svn.command.deleteSelectedFiles": "Удалить выбранные файлы", + "svn.command.copyMessage": "Копировать сообщение", + "svn.command.copyRevisionNumber": "Копировать номер редакции", + "svn.command.openDiffBase": "Открыть diff с помощью BASE", + "svn.command.openThisRevision": "Открыть эту версию", + "svn.command.refreshLogForItem": "Обновить журнал для элемента", + "svn.command.showCommitMessages": "Показать сообщения фиксации", + "svn.command.openChangesBase": "Открыть изменения с помощью BASE", + "svn.command.openChangesHead": "Открывать изменения с помощью HEAD", + "svn.command.openChangesPrev": "Открыть изменения с помощью PREV", + "svn.command.openFile": "Открыть файл", + "svn.command.openFileHead": "Открыть файл (HEAD)", + "svn.command.showPatchSelected": "Показать патч различий для выбранных", + "svn.command.showPatchAll": "Показать все патчи различий", + "svn.command.showPatchChangelist": "Показать патч из списка изменений", + "svn.command.pickPreviousCommitMessage": "Выберите предыдущее сообщение фиксации", + "svn.command.refresh": "Обновить", + "svn.command.refreshRemoteChanges": "Обновить удаленные изменения", + "svn.command.removeSelected": "Удалить выбранное", + "svn.command.removeUnversioned": "Удалить неверсированные файлы", + "svn.command.rename": "Переименовать с помощью SVN", + "svn.command.addRepoPath": "Добавить репо-подобный путь", + "svn.command.openWcFile": "Открытая версия файла WC", + "svn.command.refreshLog": "Обновить журнал", + "svn.command.remove": "удалять", + "svn.command.resolveSelected": "Разрешить конфликты для выбранных", + "svn.command.resolveAll": "Разрешить все конфликты", + "svn.command.revertSelected": "Вернуть выбранный файл", + "svn.command.revertAll": "Отменить все изменения", + "svn.command.revertChange": "Отменить изменение", + "svn.command.revertSvn": "Вернуться с SVN", + "svn.command.searchLogRevision": "Журнал поиска по редакции", + "svn.command.searchLog": "Журнал поиска", + "svn.command.switchBranch": "Switch Branch", + "svn.command.updateSelected": "Обновление выбрано", + "svn.command.update": "Обновить" +} diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json new file mode 100644 index 000000000..b65154d19 --- /dev/null +++ b/package.nls.zh-cn.json @@ -0,0 +1,49 @@ +{ + "svn.description": "集成Subversion源代码控制", + "svn.command.add": "加", + "svn.command.addToIgnore": "忽略SVN中的文件/ ext(svn:ignore)", + "svn.command.openDiff": "打开差异", + "svn.command.refreshBranchChanges": "刷新分支更改", + "svn.command.setChangelist": "设定变更清单", + "svn.command.checkout": "退房", + "svn.command.cleanWorkingCopy": "清理工作副本", + "svn.command.closeRepository": "关闭储存库", + "svn.command.commitSelected": "提交选定", + "svn.command.commitChanges": "提交变更", + "svn.command.deleteSelectedFiles": "删除所选文件", + "svn.command.copyMessage": "复制讯息", + "svn.command.copyRevisionNumber": "复制修订号", + "svn.command.openDiffBase": "用BASE打开diff", + "svn.command.openThisRevision": "打开此修订版", + "svn.command.refreshLogForItem": "刷新项目的日志", + "svn.command.showCommitMessages": "显示提交消息", + "svn.command.openChangesBase": "使用BASE打开更改", + "svn.command.openChangesHead": "使用HEAD打开更改", + "svn.command.openChangesPrev": "使用PREV打开更改", + "svn.command.openFile": "打开文件", + "svn.command.openFileHead": "打开文件(HEAD)", + "svn.command.showPatchSelected": "显示所选的差异补丁", + "svn.command.showPatchAll": "显示所有差异补丁", + "svn.command.showPatchChangelist": "显示变更列表中的补丁", + "svn.command.pickPreviousCommitMessage": "选择上一个提交消息", + "svn.command.refresh": "刷新", + "svn.command.refreshRemoteChanges": "刷新远程更改", + "svn.command.removeSelected": "删除选定", + "svn.command.removeUnversioned": "删除未版本控制的文件", + "svn.command.rename": "用SVN重命名", + "svn.command.addRepoPath": "添加类似回购的路径", + "svn.command.openWcFile": "打开文件的WC版本", + "svn.command.refreshLog": "刷新日志", + "svn.command.remove": "去掉", + "svn.command.resolveSelected": "解决所选冲突", + "svn.command.resolveAll": "解决所有冲突", + "svn.command.revertSelected": "还原所选文件", + "svn.command.revertAll": "还原所有更改", + "svn.command.revertChange": "还原变更", + "svn.command.revertSvn": "使用SVN还原", + "svn.command.searchLogRevision": "按修订版本搜索日志", + "svn.command.searchLog": "搜索日志", + "svn.command.switchBranch": "开关分公司", + "svn.command.updateSelected": "更新选择", + "svn.command.update": "更新资料" +} From 67c123d3919ad40c2514fad81538d98b87bdb6c9 Mon Sep 17 00:00:00 2001 From: Chris Johnston Date: Sun, 23 Aug 2020 15:01:19 +0100 Subject: [PATCH 3/3] Updated readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 9fc3e26b2..95c627137 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,9 @@ If you use [TortoiseSVN](https://tortoisesvn.net/), make sure the option **Command Line Tools** is checked during installation and `C:\Program Files\TortoiseSVN\bin` is available in PATH. +## Translations +Please open an [issue](https://github.com/JohnstonCode/svn-scm/issues) with improvements to translations or create a [PR](https://github.com/JohnstonCode/svn-scm/pulls) to add a new languate. + ## Feedback & Contributing * Please report any bugs, suggestions or documentation requests via the