Merge branch 'i18n' of github.com:estruyf/vscode-front-matter into i18n

This commit is contained in:
Elio Struyf
2024-02-26 20:18:44 +01:00
12 changed files with 323 additions and 194 deletions
+8
View File
@@ -46,6 +46,8 @@
"settings.view.common": "Common",
"settings.view.contentFolders": "Content folders",
"settings.view.astro": "Astro",
"settings.view.integration": "Integration",
"settings.openOnStartup": "Open dashboard on startup",
"settings.contentTypes": "Content types",
"settings.contentFolders": "Content folders",
@@ -57,12 +59,17 @@
"settings.git.commitMessage": "Commit message",
"settings.git.submoduleInfo": "When working with Git submodules, you can refer to the submodule settings in the documentation.",
"settings.git.submoduleLink": "Read more about Git submodules",
"settings.integration.title": "Integration",
"settings.commonSettings.website.title": "Website and SSG settings",
"settings.commonSettings.previewUrl": "Preview URL",
"settings.commonSettings.websiteUrl": "Website URL",
"settings.commonSettings.startCommand": "SSG/Framework start command",
"settings.integrationsView.deepl.title": "DeepL",
"settings.integrationsView.deepl.intput.label": "Authentication key",
"settings.integrationsView.deepl.intput.placeholder": "Enter your DeepL authentication key",
"developer.title": "Developer mode",
"developer.reload.title": "Reload the dashboard",
"developer.reload.label": "Reload",
@@ -728,6 +735,7 @@
"listeners.dashboard.settingsListener.triggerTemplate.progress.title": "Downloading and initializing the template...",
"listeners.dashboard.settingsListener.triggerTemplate.download.error": "Failed to download the template.",
"listeners.dashboard.settingsListener.triggerTemplate.init.error": "Failed to initialize the template.",
"listeners.dashboard.settingsListener.setSecretValue.message": "Setting has been updated.",
"listeners.dashboard.snippetListener.addSnippet.missingFields.warning": "Snippet missing title or body",
"listeners.dashboard.snippetListener.addSnippet.exists.warning": "Snippet with the same title already exists",
+146 -188
View File
@@ -10,8 +10,7 @@
"color": "#0e131f",
"theme": "dark"
},
"badges": [
{
"badges": [{
"description": "version",
"url": "https://img.shields.io/github/package-json/v/estruyf/vscode-front-matter?color=green&label=vscode-front-matter&style=flat-square",
"href": "https://github.com/estruyf/vscode-front-matter"
@@ -71,8 +70,7 @@
"**/.frontmatter/config/*.json": "jsonc"
}
},
"keybindings": [
{
"keybindings": [{
"command": "frontMatter.dashboard",
"key": "alt+d"
},
@@ -90,23 +88,19 @@
}
],
"viewsContainers": {
"activitybar": [
{
"id": "frontmatter-explorer",
"title": "FM",
"icon": "$(fm-logo)"
}
]
"activitybar": [{
"id": "frontmatter-explorer",
"title": "FM",
"icon": "$(fm-logo)"
}]
},
"views": {
"frontmatter-explorer": [
{
"id": "frontMatter.explorer",
"name": "Front Matter",
"icon": "$(fm-logo)",
"type": "webview"
}
]
"frontmatter-explorer": [{
"id": "frontMatter.explorer",
"name": "Front Matter",
"icon": "$(fm-logo)",
"type": "webview"
}]
},
"configuration": {
"title": "%settings.configuration.title%",
@@ -174,8 +168,7 @@
"frontMatter.content.defaultFileType": {
"type": "string",
"default": "md",
"oneOf": [
{
"oneOf": [{
"enum": [
"md",
"mdx"
@@ -191,8 +184,7 @@
"frontMatter.content.defaultSorting": {
"type": "string",
"default": "",
"oneOf": [
{
"oneOf": [{
"enum": [
"LastModifiedAsc",
"LastModifiedDesc",
@@ -539,8 +531,7 @@
"categories"
],
"markdownDescription": "%setting.frontMatter.content.filters.markdownDescription%",
"items": [
{
"items": [{
"type": "string"
},
{
@@ -608,8 +599,7 @@
"command": {
"$id": "#scriptCommand",
"type": "string",
"anyOf": [
{
"anyOf": [{
"enum": [
"node",
"bash",
@@ -816,8 +806,7 @@
"title",
"file"
],
"anyOf": [
{
"anyOf": [{
"required": [
"schema"
]
@@ -871,8 +860,7 @@
"id",
"path"
],
"anyOf": [
{
"anyOf": [{
"required": [
"schema"
]
@@ -1113,29 +1101,26 @@
}
}
},
"default": [
{
"name": "default",
"fileTypes": null,
"fields": [
{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Caption",
"name": "caption",
"type": "string"
},
{
"title": "Alt text",
"name": "alt",
"type": "string"
}
]
}
],
"default": [{
"name": "default",
"fileTypes": null,
"fields": [{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Caption",
"name": "caption",
"type": "string"
},
{
"title": "Alt text",
"name": "alt",
"type": "string"
}
]
}],
"scope": "Media"
},
"frontMatter.media.supportedMimeTypes": {
@@ -1365,8 +1350,7 @@
"default": "",
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description%",
"not": {
"anyOf": [
{
"anyOf": [{
"const": ""
},
{
@@ -1560,8 +1544,7 @@
"type",
"name"
],
"allOf": [
{
"allOf": [{
"if": {
"properties": {
"type": {
@@ -1769,51 +1752,48 @@
"fields"
]
},
"default": [
{
"name": "default",
"pageBundle": false,
"fields": [
{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
"name": "preview",
"type": "image"
},
{
"title": "Is in draft",
"name": "draft",
"type": "boolean"
},
{
"title": "Tags",
"name": "tags",
"type": "tags"
},
{
"title": "Categories",
"name": "categories",
"type": "categories"
}
]
}
],
"default": [{
"name": "default",
"pageBundle": false,
"fields": [{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
"name": "preview",
"type": "image"
},
{
"title": "Is in draft",
"name": "draft",
"type": "boolean"
},
{
"title": "Tags",
"name": "tags",
"type": "tags"
},
{
"title": "Categories",
"name": "categories",
"type": "categories"
}
]
}],
"scope": "Taxonomy"
},
"frontMatter.taxonomy.customTaxonomy": {
@@ -1826,8 +1806,7 @@
"type": "string",
"description": "%setting.frontMatter.taxonomy.customTaxonomy.items.properties.id.description%",
"not": {
"anyOf": [
{
"anyOf": [{
"const": ""
},
{
@@ -2021,16 +2000,10 @@
"frontMatter.website.host": {
"type": "string",
"markdownDescription": "%setting.frontMatter.website.host.markdownDescription%"
},
"frontMatter.integration.deepl": {
"type": "string",
"default": "",
"markdownDescription": "%setting.frontMatter.integration.deepl.markdownDescription%"
}
}
},
"commands": [
{
"commands": [{
"command": "frontMatter.project.switch",
"title": "%command.frontMatter.project.switch%",
"category": "Front Matter",
@@ -2356,21 +2329,16 @@
}
}
],
"submenus": [
{
"id": "frontmatter.submenu",
"label": "Front Matter"
}
],
"submenus": [{
"id": "frontmatter.submenu",
"label": "Front Matter"
}],
"menus": {
"webview/context": [
{
"command": "workbench.action.webview.openDeveloperTools",
"when": "frontMatter:isDevelopment"
}
],
"editor/title": [
{
"webview/context": [{
"command": "workbench.action.webview.openDeveloperTools",
"when": "frontMatter:isDevelopment"
}],
"editor/title": [{
"command": "frontMatter.markup.heading",
"group": "navigation@-133",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
@@ -2456,14 +2424,11 @@
"when": "resourceFilename == 'frontmatter.json'"
}
],
"explorer/context": [
{
"submenu": "frontmatter.submenu",
"group": "frontmatter@1"
}
],
"frontmatter.submenu": [
{
"explorer/context": [{
"submenu": "frontmatter.submenu",
"group": "frontmatter@1"
}],
"frontmatter.submenu": [{
"command": "frontMatter.createFromTemplate",
"when": "explorerResourceIsFolder",
"group": "frontmatter@1"
@@ -2479,8 +2444,7 @@
"group": "frontmatter@3"
}
],
"commandPalette": [
{
"commandPalette": [{
"command": "frontMatter.init",
"when": "frontMatterCanInit"
},
@@ -2637,8 +2601,7 @@
"when": "frontMatter:file:isValid == true"
}
],
"view/title": [
{
"view/title": [{
"command": "frontMatter.chatbot",
"group": "navigation@0",
"when": "view == frontMatter.explorer"
@@ -2670,57 +2633,52 @@
}
]
},
"grammars": [
{
"path": "./syntaxes/hugo.tmLanguage.json",
"scopeName": "frontmatter.markdown.hugo",
"injectTo": [
"text.html.markdown"
]
}
],
"walkthroughs": [
{
"id": "frontmatter.welcome",
"title": "Get started with Front Matter",
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
"steps": [
{
"id": "frontmatter.welcome.init",
"title": "Get started",
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
"media": {
"markdown": "assets/walkthrough/get-started.md"
},
"completionEvents": [
"onContext:frontMatterInitialized"
]
"grammars": [{
"path": "./syntaxes/hugo.tmLanguage.json",
"scopeName": "frontmatter.markdown.hugo",
"injectTo": [
"text.html.markdown"
]
}],
"walkthroughs": [{
"id": "frontmatter.welcome",
"title": "Get started with Front Matter",
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
"steps": [{
"id": "frontmatter.welcome.init",
"title": "Get started",
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
"media": {
"markdown": "assets/walkthrough/get-started.md"
},
{
"id": "frontmatter.welcome.documentation",
"title": "Documentation",
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
"media": {
"markdown": "assets/walkthrough/documentation.md"
},
"completionEvents": [
"onLink:https://frontmatter.codes/docs"
]
"completionEvents": [
"onContext:frontMatterInitialized"
]
},
{
"id": "frontmatter.welcome.documentation",
"title": "Documentation",
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
"media": {
"markdown": "assets/walkthrough/documentation.md"
},
{
"id": "frontmatter.welcome.supporter",
"title": "Support the project",
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
"media": {
"markdown": "assets/walkthrough/support-the-project.md"
},
"completionEvents": [
"onLink:https://github.com/sponsors/estruyf"
]
}
]
}
]
"completionEvents": [
"onLink:https://frontmatter.codes/docs"
]
},
{
"id": "frontmatter.welcome.supporter",
"title": "Support the project",
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
"media": {
"markdown": "assets/walkthrough/support-the-project.md"
},
"completionEvents": [
"onLink:https://github.com/sponsors/estruyf"
]
}
]
}]
},
"scripts": {
"dev:ext": "npm run clean && npm run localization:generate && npm-run-all --parallel watch:*",
@@ -2849,4 +2807,4 @@
"dependencies": {
"@radix-ui/react-dropdown-menu": "^2.0.6"
}
}
}
+1 -2
View File
@@ -76,7 +76,7 @@
"setting.frontMatter.content.pageFolders.items.properties.filePrefix.description": "Defines a prefix for the file name.",
"setting.frontMatter.content.pageFolders.items.properties.contentTypes.description": "Defines which content types can be used for the current location. If not defined, all content types will be available.",
"setting.frontMatter.content.pageFolders.items.properties.disableCreation.description": "Disable the creation of new content in the folder.",
"setting.frontMatter.content.pageFolders.items.properties.defaultLocale.description": "Set the page folder as a default locale for the content. All content from this folder is translatable to the languages defined in the `frontMatter.content.i18n` setting.",
"setting.frontMatter.content.pageFolders.items.properties.defaultLocale.description": "Set the default locale ID for the page folder. All content from this folder is translatable to the languages defined in the `frontMatter.content.i18n` setting.",
"setting.frontMatter.content.pageFolders.items.properties.locales.description": "Define the locales for the page folder. This will be used for the translation of the content.",
"setting.frontMatter.content.i18n.markdownDescription": "Specify the locales you want to use for your website. This setting can be overwritten on page folder level. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.content.i18n)",
"setting.frontMatter.content.i18n.items.properties.title.description": "Title of the locale",
@@ -268,7 +268,6 @@
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "Specify the name of the custom field type to use.",
"setting.frontMatter.taxonomy.contentTypes.items.properties.clearEmpty.description": "Specify if the empty values should be cleared.",
"setting.frontMatter.website.host.markdownDescription": "Specify the host URL of your website. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
"setting.frontMatter.integration.deepl.markdownDescription": "Specify the DeepL API key to use for the translation of your content. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.integration.deepl)",
"command.frontMatter.settings.refresh": "Refresh Front Matter Settings",
"setting.frontMatter.config.dynamicFilePath.markdownDescription": "Specify the path to the dynamic config file (ex: [[workspace]]/config.js). [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)",
"setting.frontMatter.taxonomy.contentTypes.items.properties.allowAsSubContent.description": "Specify if the content type can be used as sub content.",
+2 -2
View File
@@ -10,7 +10,7 @@ import {
openFileInEditor,
parseWinPath
} from '../helpers';
import { COMMAND_NAME, SETTING_CONTENT_I18N, SETTING_INTEGRATION_DEEPL } from '../constants';
import { COMMAND_NAME, ExtensionState, SETTING_CONTENT_I18N } from '../constants';
import { ContentFolder, Field, I18nConfig, ContentType as IContentType } from '../models';
import { join, parse } from 'path';
import { existsAsync } from '../utils';
@@ -336,7 +336,7 @@ export class i18n {
targetLocale: I18nConfig
) {
return new Promise<ParsedFrontMatter>(async (resolve) => {
const authKey = Settings.get<string>(SETTING_INTEGRATION_DEEPL);
const authKey = await Extension.getInstance().getSecret(ExtensionState.Secrets.DeeplApiKey);
if (!authKey) {
resolve(article);
return;
+4
View File
@@ -30,5 +30,9 @@ export const ExtensionState = {
v7_0_0: {
dateFields: `frontMatter:Updates:v7.0.0:dateFields`
}
},
Secrets: {
DeeplApiKey: `frontMatter:Secrets:DeeplApiKey`
}
};
+4
View File
@@ -17,6 +17,10 @@ export const GeneralCommands = {
getBranch: 'getBranch',
selectBranch: 'gitSelectBranch'
},
secrets: {
get: 'getSecret',
set: 'setSecret'
},
runCommand: 'runCommand',
getLocalization: 'getLocalization',
openOnWebsite: 'openOnWebsite'
-2
View File
@@ -114,8 +114,6 @@ export const SETTING_SNIPPETS_WRAPPER = 'snippets.wrapper.enabled';
export const SETTING_WEBSITE_URL = 'website.host';
export const SETTING_INTEGRATION_DEEPL = 'integration.deepl';
/**
* Sponsors only settings
*/
@@ -0,0 +1,58 @@
import * as React from 'react';
import * as l10n from '@vscode/l10n';
import { messageHandler } from '@estruyf/vscode/dist/client';
import { LocalizationKey } from '../../../localization';
import { GeneralCommands, ExtensionState } from '../../../constants';
import { SettingsInput } from './SettingsInput';
import { VSCodeButton } from '@vscode/webview-ui-toolkit/react';
export interface IIntegrationsViewProps { }
export const IntegrationsView: React.FunctionComponent<IIntegrationsViewProps> = ({ }: React.PropsWithChildren<IIntegrationsViewProps>) => {
const [deeplApiKey, setDeeplApiKey] = React.useState<string>('');
const [crntDeeplApiKey, setCrntDeeplApiKey] = React.useState<string>('');
const onSave = React.useCallback(() => {
messageHandler.request<string>(GeneralCommands.toVSCode.secrets.set, {
key: ExtensionState.Secrets.DeeplApiKey,
value: crntDeeplApiKey
}).then((apiKey: string) => {
setDeeplApiKey(apiKey);
});
}, [crntDeeplApiKey]);
const onChange = (_: string, value: string) => {
setCrntDeeplApiKey(value);
};
React.useEffect(() => {
messageHandler.request<string>(GeneralCommands.toVSCode.secrets.get, ExtensionState.Secrets.DeeplApiKey).then((apiKey: string) => {
setDeeplApiKey(apiKey);
setCrntDeeplApiKey(apiKey);
});
}, []);
return (
<div className='w-full divide-y divide-[var(--frontmatter-border)]'>
<div className='py-4 space-y-4'>
<h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsIntegrationsViewDeeplTitle)}</h2>
<SettingsInput
label={l10n.t(LocalizationKey.settingsIntegrationsViewDeeplIntputLabel)}
name={ExtensionState.Secrets.DeeplApiKey}
value={crntDeeplApiKey || ""}
placeholder={l10n.t(LocalizationKey.settingsIntegrationsViewDeeplIntputPlaceholder)}
onChange={onChange}
/>
<div className={`mt-4 flex gap-2`}>
<VSCodeButton
onClick={onSave}
disabled={deeplApiKey === crntDeeplApiKey}>
{l10n.t(LocalizationKey.commonSave)}
</VSCodeButton>
</div>
</div>
</div>
);
};
@@ -12,6 +12,7 @@ import { COMMAND_NAME } from '../../../constants';
import { ArrowPathIcon } from '@heroicons/react/24/outline';
import { VSCodePanelTab, VSCodePanelView, VSCodePanels } from '@vscode/webview-ui-toolkit/react';
import { CommonSettings } from './CommonSettings';
import { IntegrationsView } from './IntegrationsView';
export interface ISettingsViewProps { }
@@ -54,6 +55,8 @@ export const SettingsView: React.FunctionComponent<ISettingsViewProps> = (_: Rea
)
}
<VSCodePanelTab id="view-4">{l10n.t(LocalizationKey.settingsViewIntegration)}</VSCodePanelTab>
<VSCodePanelView id="view-1">
<CommonSettings />
</VSCodePanelView>
@@ -82,6 +85,10 @@ export const SettingsView: React.FunctionComponent<ISettingsViewProps> = (_: Rea
</VSCodePanelView>
)
}
<VSCodePanelView id="view-4">
<IntegrationsView />
</VSCodePanelView>
</VSCodePanels>
</div>
)
+8
View File
@@ -424,6 +424,14 @@ export class Extension {
}
}
public async getSecret(key: string): Promise<string | undefined> {
return this.ctx.secrets.get(key);
}
public async setSecret(key: string, value: string): Promise<void> {
return this.ctx.secrets.store(key, value);
}
public isBetaVersion() {
return basename(this.ctx.globalStorageUri.fsPath) === EXTENSION_BETA_ID;
}
@@ -4,6 +4,7 @@ import { Folders } from '../../commands/Folders';
import {
COMMAND_NAME,
ExtensionState,
GeneralCommands,
SETTING_CONTENT_STATIC_FOLDER,
SETTING_FRAMEWORK_ID,
SETTING_PREVIEW_HOST
@@ -61,9 +62,21 @@ export class SettingsListener extends BaseListener {
case DashboardMessage.setSettings:
this.setConfigSettings(msg);
break;
case GeneralCommands.toVSCode.secrets.get:
this.getSecretValue(msg.command, msg.payload, msg.requestId);
break;
case GeneralCommands.toVSCode.secrets.set:
this.setSecretValue(msg.command, msg.payload, msg.requestId);
break;
}
}
/**
* Retrieves the configuration settings based on the provided payload.
* @param command - The command to execute.
* @param requestId - The ID of the request.
* @param payload - The payload containing the settings to retrieve.
*/
public static async getConfigSettings({ command, requestId, payload }: PostMessageData) {
if (!command || !requestId || !payload) {
return;
@@ -96,6 +109,10 @@ export class SettingsListener extends BaseListener {
this.sendRequest(command as any, requestId, true);
}
/**
* Switches the current project to the specified project.
* @param project - The name of the project to switch to.
*/
public static async switchProject(project: string) {
if (project) {
this.sendMsg(DashboardCommand.loading, 'loading' as LoadingType);
@@ -123,6 +140,50 @@ export class SettingsListener extends BaseListener {
}
}
/**
* Retrieves the secret value for a given command and value.
* @param command - The command to retrieve the secret value for.
* @param key - The key associated with the secret.
* @param requestId - Optional. The ID of the request.
* @returns A Promise that resolves to the secret value.
*/
private static async getSecretValue(command: string, key: string, requestId?: string) {
if (!command || !requestId) {
return;
}
const extension = Extension.getInstance();
const value = await extension.getSecret(key);
this.sendRequest(command as any, requestId, value);
}
/**
* Sets the secret value for a given key.
* @param command - The command to execute.
* @param key - The key for the secret value.
* @param value - The secret value to set.
* @param requestId - Optional. The request ID.
*/
private static async setSecretValue(
command: string,
{ key, value }: { key: string; value: string },
requestId?: string
) {
if (!command || !requestId || !key) {
return;
}
const extension = Extension.getInstance();
await extension.setSecret(key, value || '');
Notifications.info(
l10n.t(LocalizationKey.listenersDashboardSettingsListenerSetSecretValueMessage)
);
this.sendRequest(command as any, requestId, true);
}
/**
* Update a setting from the dashboard
* @param data
+24
View File
@@ -175,6 +175,10 @@ export enum LocalizationKey {
* Astro
*/
settingsViewAstro = 'settings.view.astro',
/**
* Integration
*/
settingsViewIntegration = 'settings.view.integration',
/**
* Open dashboard on startup
*/
@@ -219,6 +223,10 @@ export enum LocalizationKey {
* Read more about Git submodules
*/
settingsGitSubmoduleLink = 'settings.git.submoduleLink',
/**
* Integration
*/
settingsIntegrationTitle = 'settings.integration.title',
/**
* Website and SSG settings
*/
@@ -235,6 +243,18 @@ export enum LocalizationKey {
* SSG/Framework start command
*/
settingsCommonSettingsStartCommand = 'settings.commonSettings.startCommand',
/**
* DeepL
*/
settingsIntegrationsViewDeeplTitle = 'settings.integrationsView.deepl.title',
/**
* Authentication key
*/
settingsIntegrationsViewDeeplIntputLabel = 'settings.integrationsView.deepl.intput.label',
/**
* Enter your DeepL authentication key
*/
settingsIntegrationsViewDeeplIntputPlaceholder = 'settings.integrationsView.deepl.intput.placeholder',
/**
* Developer mode
*/
@@ -2408,6 +2428,10 @@ export enum LocalizationKey {
* Failed to initialize the template.
*/
listenersDashboardSettingsListenerTriggerTemplateInitError = 'listeners.dashboard.settingsListener.triggerTemplate.init.error',
/**
* Setting has been updated.
*/
listenersDashboardSettingsListenerSetSecretValueMessage = 'listeners.dashboard.settingsListener.setSecretValue.message',
/**
* Snippet missing title or body
*/