mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-07-06 09:51:29 +02:00
Merge branch 'issue/850' of github.com:wottpal/vscode-front-matter into wottpal-issue/850
This commit is contained in:
@@ -583,8 +583,13 @@
|
||||
"commands.i18n.create.success.created": "Created \"{0}\" i18n content file.",
|
||||
"commands.i18n.create.quickPick.title": "Create content for locale",
|
||||
"commands.i18n.create.quickPick.placeHolder": "To which locale do you want to create a new content?",
|
||||
"commands.i18n.createOrOpen.quickPick.title": "Open or create translation",
|
||||
"commands.i18n.createOrOpen.quickPick.category.existing": "Existing translations",
|
||||
"commands.i18n.createOrOpen.quickPick.action.open": "Open \"{0}\"",
|
||||
"commands.i18n.createOrOpen.quickPick.category.new": "New translations",
|
||||
"commands.i18n.createOrOpen.quickPick.action.create": "Create \"{0}\"",
|
||||
"commands.i18n.translate.progress.title": "Translating content...",
|
||||
|
||||
|
||||
"commands.preview.panel.title": "Preview: {0}",
|
||||
"commands.preview.askUserToPickFolder.title": "Select the folder of the article to preview",
|
||||
|
||||
|
||||
+10
-1
@@ -2393,6 +2393,15 @@
|
||||
"title": "%command.frontMatter.cache.clear%",
|
||||
"category": "Front Matter"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.i18n.createOrOpen",
|
||||
"title": "%command.frontMatter.i18n.createOrOpen%",
|
||||
"category": "Front Matter",
|
||||
"icon": {
|
||||
"light": "assets/icons/i18n-light.svg",
|
||||
"dark": "assets/icons/i18n-dark.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.i18n.create",
|
||||
"title": "%command.frontMatter.i18n.create%",
|
||||
@@ -2448,7 +2457,7 @@
|
||||
"when": "frontMatter:file:isValid == true"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.i18n.create",
|
||||
"command": "frontMatter.i18n.createOrOpen",
|
||||
"group": "navigation@-127",
|
||||
"when": "frontMatter:file:isValid && frontMatter:i18n:enabled"
|
||||
},
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"command.frontMatter.git.sync": "Sync",
|
||||
"command.frontMatter.cache.clear": "Clear cache",
|
||||
"command.frontMatter.i18n.create": "Create new translation",
|
||||
"command.frontMatter.i18n.createOrOpen": "Create or open translation",
|
||||
"settings.configuration.title": "Front Matter: use frontmatter.json for shared team settings",
|
||||
"setting.frontMatter.projects.markdownDescription": "Specify the list of projects to load in the Front Matter CMS. [Local](https://file%2B.vscode-resource.vscode-cdn.net/Users/eliostruyf/nodejs/frontmatter-test-projects/astro-blog/test.html) - [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.projects) - [View in VS Code](vscode://simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.projects%22%5D)",
|
||||
"setting.frontMatter.projects.items.properties.name.markdownDescription": "Specify the name of the project.",
|
||||
|
||||
+187
-1
@@ -1,4 +1,14 @@
|
||||
import { ProgressLocation, Uri, commands, window, workspace } from 'vscode';
|
||||
import {
|
||||
ProgressLocation,
|
||||
QuickPickItem,
|
||||
QuickPickItemKind,
|
||||
QuickPickOptions,
|
||||
ThemeIcon,
|
||||
Uri,
|
||||
commands,
|
||||
window,
|
||||
workspace
|
||||
} from 'vscode';
|
||||
import {
|
||||
ArticleHelper,
|
||||
ContentType,
|
||||
@@ -32,6 +42,7 @@ export class i18n {
|
||||
const subscriptions = Extension.getInstance().subscriptions;
|
||||
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.i18n.create, i18n.create));
|
||||
subscriptions.push(commands.registerCommand(COMMAND_NAME.i18n.createOrOpen, i18n.createOrOpen));
|
||||
|
||||
i18n.clearFiles();
|
||||
}
|
||||
@@ -391,6 +402,181 @@ export class i18n {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles the process of creating a new translation file if it doesn't exist,
|
||||
* or opening an existing translation file if it's already present.
|
||||
* @param filePath The path of the file where the new content file should be created or being switched to. Behaves like `create` if not provided.
|
||||
*/
|
||||
private static async createOrOpen(fileUri?: Uri | string) {
|
||||
if (!fileUri) {
|
||||
const filePath = ArticleHelper.getActiveFile();
|
||||
fileUri = filePath ? Uri.file(filePath) : undefined;
|
||||
}
|
||||
|
||||
if (!fileUri) {
|
||||
Notifications.warning(l10n.t(LocalizationKey.commandsI18nCreateWarningNoFileSelected));
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof fileUri === 'string') {
|
||||
fileUri = Uri.file(fileUri);
|
||||
}
|
||||
|
||||
const pageFolder = await Folders.getPageFolderByFilePath(fileUri.fsPath);
|
||||
if (!pageFolder || !pageFolder.localeSourcePath) {
|
||||
Notifications.error(l10n.t(LocalizationKey.commandsI18nCreateErrorNoContentFolder));
|
||||
return;
|
||||
}
|
||||
|
||||
let article = await ArticleHelper.getFrontMatterByPath(fileUri.fsPath);
|
||||
if (!article) {
|
||||
Notifications.warning(l10n.t(LocalizationKey.commandsI18nCreateWarningNoFile));
|
||||
return;
|
||||
}
|
||||
|
||||
const contentType = await ArticleHelper.getContentType(article);
|
||||
if (!contentType) {
|
||||
Notifications.warning(l10n.t(LocalizationKey.commandsI18nCreateWarningNoContentType));
|
||||
return;
|
||||
}
|
||||
|
||||
const i18nSettings = await i18n.getSettings(fileUri.fsPath);
|
||||
if (!i18nSettings) {
|
||||
Notifications.warning(l10n.t(LocalizationKey.commandsI18nCreateWarningNoConfig));
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceLocale = await i18n.getLocale(fileUri.fsPath);
|
||||
if (!sourceLocale || !sourceLocale.locale) {
|
||||
Notifications.warning(l10n.t(LocalizationKey.commandsI18nCreateErrorNoLocaleDefinition));
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine translation file paths
|
||||
const fileInfo = parse(fileUri.fsPath);
|
||||
let pageBundleDir = '';
|
||||
if (await ArticleHelper.isPageBundle(fileUri.fsPath)) {
|
||||
const dir = ArticleHelper.getPageFolderFromBundlePath(fileUri.fsPath);
|
||||
pageBundleDir = fileUri.fsPath.replace(dir, '');
|
||||
pageBundleDir = join(parse(pageBundleDir).dir);
|
||||
}
|
||||
|
||||
// Gather target locales & metadata
|
||||
const translations = (await i18n.getTranslations(fileUri.fsPath)) || {};
|
||||
const targetLocales = i18nSettings
|
||||
.filter((i18n) => {
|
||||
return i18n.path && i18n.locale !== sourceLocale.locale;
|
||||
})
|
||||
.map((i18n) => {
|
||||
return {
|
||||
...i18n,
|
||||
dir: join(pageFolder.localeSourcePath!, i18n.path!, pageBundleDir),
|
||||
absolutePath: join(
|
||||
pageFolder.localeSourcePath!,
|
||||
i18n.path!,
|
||||
pageBundleDir,
|
||||
fileInfo.base
|
||||
),
|
||||
relativePath: join(i18n.path!, pageBundleDir, fileInfo.base)
|
||||
};
|
||||
})
|
||||
.sort((a, b) => (a.title || a.locale).localeCompare(b.title || b.locale));
|
||||
|
||||
if (targetLocales.length === 0) {
|
||||
Notifications.warning(l10n.t(LocalizationKey.commandsI18nCreateErrorNoLocales));
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure quick pick items & options
|
||||
const existingTargetLocales = targetLocales.filter((i18n) => translations[i18n.locale]);
|
||||
const newTargetLocales = targetLocales.filter((i18n) => !translations[i18n.locale]);
|
||||
const quickPickItems: QuickPickItem[] = [
|
||||
...(existingTargetLocales.length
|
||||
? [
|
||||
{
|
||||
label: l10n.t(LocalizationKey.commandsI18nCreateOrOpenQuickPickCategoryExisting),
|
||||
kind: QuickPickItemKind.Separator
|
||||
},
|
||||
...existingTargetLocales.map((i18n) => ({
|
||||
label: i18n.title || i18n.locale,
|
||||
detail: l10n.t(LocalizationKey.commandsI18nCreateOrOpenQuickPickActionOpen, i18n.relativePath)
|
||||
}))
|
||||
]
|
||||
: []),
|
||||
...(newTargetLocales.length
|
||||
? [
|
||||
{
|
||||
label: l10n.t(LocalizationKey.commandsI18nCreateOrOpenQuickPickCategoryNew),
|
||||
kind: QuickPickItemKind.Separator
|
||||
},
|
||||
...newTargetLocales.map((i18n) => ({
|
||||
label: i18n.title || i18n.locale,
|
||||
detail: `$(file-add) ${l10n.t(LocalizationKey.commandsI18nCreateOrOpenQuickPickActionCreate, i18n.relativePath)}`
|
||||
}))
|
||||
]
|
||||
: [])
|
||||
];
|
||||
const quickPickOptions: QuickPickOptions = {
|
||||
title: l10n.t(LocalizationKey.commandsI18nCreateOrOpenQuickPickTitle),
|
||||
ignoreFocusOut: true,
|
||||
matchOnDetail: true
|
||||
};
|
||||
|
||||
const localeItem = await window.showQuickPick<QuickPickItem>(quickPickItems, quickPickOptions);
|
||||
const locale = localeItem?.label;
|
||||
if (!locale) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetLocale = targetLocales.find(
|
||||
(i18n) => i18n.title === locale || i18n.locale === locale
|
||||
);
|
||||
if (!targetLocale || !targetLocale.path) {
|
||||
Notifications.warning(l10n.t(LocalizationKey.commandsI18nCreateWarningNoConfig));
|
||||
return;
|
||||
}
|
||||
|
||||
// If it exists, open the translation file
|
||||
if (await existsAsync(targetLocale.absolutePath)) {
|
||||
await openFileInEditor(targetLocale.absolutePath);
|
||||
return;
|
||||
}
|
||||
|
||||
// If it doesn't exist, create the new translation file & update front matter
|
||||
if (!(await existsAsync(targetLocale.dir))) {
|
||||
await workspace.fs.createDirectory(Uri.file(targetLocale.dir));
|
||||
}
|
||||
|
||||
article = await i18n.updateFrontMatter(
|
||||
article,
|
||||
fileUri.fsPath,
|
||||
contentType,
|
||||
sourceLocale,
|
||||
targetLocale,
|
||||
targetLocale.dir
|
||||
);
|
||||
if (sourceLocale?.locale) {
|
||||
article = await i18n.translate(article, sourceLocale, targetLocale);
|
||||
}
|
||||
|
||||
const newFileUri = Uri.file(targetLocale.absolutePath);
|
||||
await workspace.fs.writeFile(
|
||||
newFileUri,
|
||||
Buffer.from(ArticleHelper.stringifyFrontMatter(article.content, article.data))
|
||||
);
|
||||
|
||||
await openFileInEditor(targetLocale.absolutePath);
|
||||
|
||||
PagesListener.refresh();
|
||||
|
||||
Notifications.info(
|
||||
l10n.t(
|
||||
LocalizationKey.commandsI18nCreateSuccessCreated,
|
||||
sourceLocale.title || sourceLocale.locale
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given article from the source locale to the target locale using DeepL translation service.
|
||||
* @param article - The article to be translated.
|
||||
|
||||
@@ -70,7 +70,8 @@ export const COMMAND_NAME = {
|
||||
|
||||
// i18n
|
||||
i18n: {
|
||||
create: getCommandName('i18n.create')
|
||||
create: getCommandName('i18n.create'),
|
||||
createOrOpen: getCommandName('i18n.createOrOpen')
|
||||
},
|
||||
|
||||
// Project
|
||||
|
||||
@@ -1884,6 +1884,26 @@ export enum LocalizationKey {
|
||||
* To which locale do you want to create a new content?
|
||||
*/
|
||||
commandsI18nCreateQuickPickPlaceHolder = 'commands.i18n.create.quickPick.placeHolder',
|
||||
/**
|
||||
* Open or create translation
|
||||
*/
|
||||
commandsI18nCreateOrOpenQuickPickTitle = 'commands.i18n.createOrOpen.quickPick.title',
|
||||
/**
|
||||
* Existing translations
|
||||
*/
|
||||
commandsI18nCreateOrOpenQuickPickCategoryExisting = 'commands.i18n.createOrOpen.quickPick.category.existing',
|
||||
/**
|
||||
* Open "{0}"
|
||||
*/
|
||||
commandsI18nCreateOrOpenQuickPickActionOpen = 'commands.i18n.createOrOpen.quickPick.action.open',
|
||||
/**
|
||||
* New translations
|
||||
*/
|
||||
commandsI18nCreateOrOpenQuickPickCategoryNew = 'commands.i18n.createOrOpen.quickPick.category.new',
|
||||
/**
|
||||
* Create "{0}"
|
||||
*/
|
||||
commandsI18nCreateOrOpenQuickPickActionCreate = 'commands.i18n.createOrOpen.quickPick.action.create',
|
||||
/**
|
||||
* Translating content...
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user