mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-09 10:22:55 +02:00
#598: Add localization support to the panel + scripts
This commit is contained in:
@@ -1,4 +1,12 @@
|
||||
{
|
||||
"header.createContent": "Inhalte erstellen",
|
||||
"header.startup.label": "Beim Start öffnen?"
|
||||
"header.startup.label": "Beim Start öffnen?",
|
||||
"dashboard.header.createContent": "🚧: Create content",
|
||||
"dashboard.header.startup.label": "🚧: Open on startup?",
|
||||
"panel.actions.title": "🚧: Actions",
|
||||
"panel.actions.openDashboard": "🚧: Open dashboard",
|
||||
"panel.actions.openPreview": "🚧: Open preview",
|
||||
"panel.actions.startServer": "🚧: Start server",
|
||||
"panel.actions.stopServer": "🚧: Stop server",
|
||||
"panel.actions.createContent": "🚧: Create content"
|
||||
}
|
||||
@@ -1,4 +1,11 @@
|
||||
{
|
||||
"header.createContent": "Create content",
|
||||
"header.startup.label": "Open on startup?"
|
||||
"dashboard.header.createContent": "Create content",
|
||||
"dashboard.header.startup.label": "Open on startup?",
|
||||
|
||||
"panel.actions.title": "Actions",
|
||||
"panel.actions.openDashboard": "Open dashboard",
|
||||
"panel.actions.openPreview": "Open preview",
|
||||
"panel.actions.startServer": "Start server",
|
||||
"panel.actions.stopServer": "Stop server",
|
||||
"panel.actions.createContent": "Create content"
|
||||
}
|
||||
+4
-2
@@ -2374,7 +2374,7 @@
|
||||
}]
|
||||
},
|
||||
"scripts": {
|
||||
"dev:ext": "npm run clean && npm-run-all --parallel watch:*",
|
||||
"dev:ext": "npm run clean && npm run localization:generate && npm-run-all --parallel watch:*",
|
||||
"vscode:prepublish": "npm run clean && npm-run-all --parallel prod:*",
|
||||
"build:ext": "npm run clean && npm-run-all --parallel dev:build:*",
|
||||
"watch:ext": "webpack --mode development --watch --config ./webpack/extension.config.js",
|
||||
@@ -2392,7 +2392,9 @@
|
||||
"clean:test": "rm ./e2e/sample/frontmatter.json || exit 0 && rm -rf ./e2e/sample/.frontmatter || exit 0",
|
||||
"test": "pnpm lint; tsc -p tsconfig.e2e.json && npm run clean:test && pnpm i -g @vscode/vsce && node ./e2e/out/runTests.js",
|
||||
"lint": "eslint --max-warnings=0 ./src/{commands,components}",
|
||||
"prettier": "prettier --write ./src"
|
||||
"prettier": "prettier --write ./src",
|
||||
"localization:generate": "node scripts/generate-localization-enum.js",
|
||||
"localization:sync": "node scripts/sync-localization.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.8.2",
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const camlCase = (str) => {
|
||||
const words = str.split('.');
|
||||
const firstWord = words.shift();
|
||||
const rest = words.map((word) => {
|
||||
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||
});
|
||||
return firstWord + rest.join('');
|
||||
};
|
||||
|
||||
(async () => {
|
||||
// Get the EN file
|
||||
const enFile = fs.readFileSync(path.join(__dirname, '../l10n/bundle.l10n.json'), 'utf8');
|
||||
|
||||
// Parse the EN file
|
||||
const en = JSON.parse(enFile);
|
||||
|
||||
const keys = Object.keys(en);
|
||||
|
||||
// Create an enum file
|
||||
const enumFile = fs.createWriteStream(path.join(__dirname, '../src/localization/localization.enum.ts'));
|
||||
|
||||
// Write the enum file header
|
||||
enumFile.write(`export enum LocalizationKey {\n`);
|
||||
|
||||
// Write the enum values
|
||||
keys.forEach((key, index) => {
|
||||
enumFile.write(` ${camlCase(key)} = '${key}'${index === keys.length - 1 ? '' : ','}\n`);
|
||||
});
|
||||
|
||||
// Write the enum file footer
|
||||
enumFile.write(`}\n`);
|
||||
|
||||
// Close the enum file
|
||||
enumFile.close();
|
||||
})();
|
||||
@@ -0,0 +1,33 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
(async () => {
|
||||
// Get all the files from the l10n directory
|
||||
const files = fs.readdirSync(path.join(__dirname, '../l10n'));
|
||||
|
||||
// Get the EN file
|
||||
const enFile = fs.readFileSync(path.join(__dirname, '../l10n/bundle.l10n.json'), 'utf8');
|
||||
const enContent = JSON.parse(enFile);
|
||||
const enKeys = Object.keys(enContent);
|
||||
|
||||
for (const file of files) {
|
||||
if (file.endsWith(`bundle.l10n.json`)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the file content
|
||||
const fileContent = fs.readFileSync(path.join(__dirname, `../l10n/${file}`), 'utf8');
|
||||
const content = JSON.parse(fileContent);
|
||||
|
||||
// Loop through the EN keys
|
||||
for (const key of enKeys) {
|
||||
// If the key does not exist in the file, add it
|
||||
if (!content[key]) {
|
||||
content[key] = `🚧: ${enContent[key]}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the file
|
||||
fs.writeFileSync(path.join(__dirname, `../l10n/${file}`), JSON.stringify(content, null, 2), 'utf8');
|
||||
}
|
||||
})();
|
||||
@@ -22,7 +22,8 @@ import {
|
||||
ExtensionListener,
|
||||
SnippetListener,
|
||||
TaxonomyListener,
|
||||
LogListener
|
||||
LogListener,
|
||||
LocalizationListener
|
||||
} from '../listeners/dashboard';
|
||||
import { MediaListener as PanelMediaListener } from '../listeners/panel';
|
||||
import { GitListener, ModeListener } from '../listeners/general';
|
||||
@@ -166,6 +167,7 @@ export class Dashboard {
|
||||
Dashboard.webview.webview.onDidReceiveMessage(async (msg) => {
|
||||
Logger.info(`Receiving message from webview: ${msg.command}`);
|
||||
|
||||
LocalizationListener.process(msg);
|
||||
DashboardListener.process(msg);
|
||||
ExtensionListener.process(msg);
|
||||
MediaListener.process(msg);
|
||||
|
||||
@@ -2,10 +2,12 @@ export const GeneralCommands = {
|
||||
toWebview: {
|
||||
setMode: 'setMode',
|
||||
gitSyncingStart: 'gitSyncingStart',
|
||||
gitSyncingEnd: 'gitSyncingEnd'
|
||||
gitSyncingEnd: 'gitSyncingEnd',
|
||||
setLocalization: 'setLocalization'
|
||||
},
|
||||
toVSCode: {
|
||||
openLink: 'openLink',
|
||||
gitSync: 'gitSync'
|
||||
gitSync: 'gitSync',
|
||||
getLocalization: 'getLocalization'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,8 +10,5 @@ export enum DashboardCommand {
|
||||
searchReady = 'searchReady',
|
||||
|
||||
// Taxonomy dashboard
|
||||
setTaxonomyData = 'setTaxonomyData',
|
||||
|
||||
// Localization
|
||||
setLocalization = 'setLocalization'
|
||||
setTaxonomyData = 'setTaxonomyData'
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ export enum DashboardMessage {
|
||||
moveTaxonomy = 'moveTaxonomy',
|
||||
|
||||
// Other
|
||||
getLocalization = 'getLocalization',
|
||||
getTheme = 'getTheme',
|
||||
updateSetting = 'updateSetting',
|
||||
setState = 'setState',
|
||||
|
||||
@@ -30,6 +30,7 @@ import { Startup } from './Startup';
|
||||
import { Navigation } from './Navigation';
|
||||
import { ProjectSwitcher } from './ProjectSwitcher';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
|
||||
export interface IHeaderProps {
|
||||
header?: React.ReactNode;
|
||||
@@ -169,7 +170,7 @@ export const Header: React.FunctionComponent<IHeaderProps> = ({
|
||||
<SyncButton />
|
||||
|
||||
<ChoiceButton
|
||||
title={l10n.t(`header.createContent`)}
|
||||
title={l10n.t(LocalizationKey.dashboardHeaderCreateContent)}
|
||||
choices={choiceOptions}
|
||||
onClick={createContent}
|
||||
disabled={!settings?.initialized}
|
||||
|
||||
@@ -5,6 +5,7 @@ import useThemeColors from '../../hooks/useThemeColors';
|
||||
import { DashboardMessage } from '../../DashboardMessage';
|
||||
import { SETTING_DASHBOARD_OPENONSTART } from '../../../constants';
|
||||
import * as l10n from "@vscode/l10n"
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
|
||||
export interface IStartupProps {
|
||||
settings: Settings | null;
|
||||
@@ -55,7 +56,7 @@ export const Startup: React.FunctionComponent<IStartupProps> = ({
|
||||
)
|
||||
}`}
|
||||
>
|
||||
{l10n.t(`header.startup.label`)}
|
||||
{l10n.t(LocalizationKey.dashboardHeaderStartupLabel)}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -60,7 +60,7 @@ export default function useMessages() {
|
||||
case GeneralCommands.toWebview.setMode:
|
||||
setMode(message.payload);
|
||||
break;
|
||||
case DashboardCommand.setLocalization:
|
||||
case GeneralCommands.toWebview.setLocalization:
|
||||
l10n.config({
|
||||
contents: message.payload
|
||||
})
|
||||
@@ -76,7 +76,7 @@ export default function useMessages() {
|
||||
Messenger.send(DashboardMessage.getTheme);
|
||||
Messenger.send(DashboardMessage.getData);
|
||||
Messenger.send(DashboardMessage.getMode);
|
||||
Messenger.send(DashboardMessage.getLocalization);
|
||||
Messenger.send(GeneralCommands.toVSCode.getLocalization);
|
||||
|
||||
return () => {
|
||||
Messenger.unlisten(messageListener);
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
TaxonomyListener,
|
||||
DataListener,
|
||||
SettingsListener,
|
||||
FieldsListener
|
||||
FieldsListener,
|
||||
LocalizationListener
|
||||
} from './../listeners/panel';
|
||||
import { SETTING_EXPERIMENTAL, SETTING_EXTENSIBILITY_SCRIPTS, TelemetryEvent } from '../constants';
|
||||
import {
|
||||
@@ -98,6 +99,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
webviewView.webview.onDidReceiveMessage(async (msg) => {
|
||||
Logger.info(`Receiving message from webview to panel: ${msg.command}`);
|
||||
|
||||
LocalizationListener.process(msg);
|
||||
FieldsListener.process(msg);
|
||||
ArticleListener.process(msg);
|
||||
DataListener.process(msg);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { GeneralCommands } from '../../constants';
|
||||
import { PostMessageData } from '../../models';
|
||||
import { BaseListener } from './BaseListener';
|
||||
import { getLocalizationFile } from '../../utils/getLocalizationFile';
|
||||
|
||||
export class LocalizationListener extends BaseListener {
|
||||
/**
|
||||
* Process the messages
|
||||
* @param msg
|
||||
*/
|
||||
public static process(msg: PostMessageData) {
|
||||
switch (msg.command) {
|
||||
case GeneralCommands.toVSCode.getLocalization:
|
||||
this.getLocalization();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static async getLocalization() {
|
||||
const fileContents = await getLocalizationFile();
|
||||
|
||||
this.sendMsg(GeneralCommands.toWebview.setLocalization as any, fileContents);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { join } from 'path';
|
||||
import { commands, Uri, l10n } from 'vscode';
|
||||
import { commands, Uri } from 'vscode';
|
||||
import { Folders } from '../../commands/Folders';
|
||||
import {
|
||||
COMMAND_NAME,
|
||||
@@ -21,7 +21,6 @@ import { DataListener } from '../panel';
|
||||
import { MarkdownFoldingProvider } from '../../providers/MarkdownFoldingProvider';
|
||||
import { ModeSwitch } from '../../services/ModeSwitch';
|
||||
import { PagesListener } from './PagesListener';
|
||||
import { readFileAsync } from '../../utils';
|
||||
|
||||
export class SettingsListener extends BaseListener {
|
||||
/**
|
||||
@@ -35,9 +34,6 @@ export class SettingsListener extends BaseListener {
|
||||
case DashboardMessage.getData:
|
||||
this.getSettings();
|
||||
break;
|
||||
case DashboardMessage.getLocalization:
|
||||
this.getLocalization();
|
||||
break;
|
||||
case DashboardMessage.updateSetting:
|
||||
this.update(msg.payload);
|
||||
break;
|
||||
@@ -53,16 +49,6 @@ export class SettingsListener extends BaseListener {
|
||||
}
|
||||
}
|
||||
|
||||
public static async getLocalization() {
|
||||
const localeFilePath =
|
||||
l10n.uri?.fsPath ||
|
||||
Uri.parse(`${Extension.getInstance().extensionPath}/l10n/bundle.l10n.json`).fsPath;
|
||||
|
||||
const fileContents = await readFileAsync(localeFilePath, 'utf-8');
|
||||
|
||||
this.sendMsg(DashboardCommand.setLocalization, fileContents);
|
||||
}
|
||||
|
||||
public static async switchProject(project: string) {
|
||||
if (project) {
|
||||
this.sendMsg(DashboardCommand.loading, true);
|
||||
|
||||
@@ -9,3 +9,4 @@ export * from './SnippetListener';
|
||||
export * from './TelemetryListener';
|
||||
export * from './TaxonomyListener';
|
||||
export * from './LogListener';
|
||||
export * from './LocalizationListener';
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './ModeListener';
|
||||
export * from './GitListener';
|
||||
export * from './ModeListener';
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { GeneralCommands } from '../../constants';
|
||||
import { PostMessageData } from '../../models';
|
||||
import { BaseListener } from './BaseListener';
|
||||
import { getLocalizationFile } from '../../utils/getLocalizationFile';
|
||||
|
||||
export class LocalizationListener extends BaseListener {
|
||||
/**
|
||||
* Process the messages
|
||||
* @param msg
|
||||
*/
|
||||
public static process(msg: PostMessageData) {
|
||||
switch (msg.command) {
|
||||
case GeneralCommands.toVSCode.getLocalization:
|
||||
this.getLocalization();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static async getLocalization() {
|
||||
const fileContents = await getLocalizationFile();
|
||||
|
||||
this.sendMsg(GeneralCommands.toWebview.setLocalization as any, fileContents);
|
||||
}
|
||||
}
|
||||
@@ -7,3 +7,4 @@ export * from './MediaListener';
|
||||
export * from './ScriptListener';
|
||||
export * from './SettingsListener';
|
||||
export * from './TaxonomyListener';
|
||||
export * from './LocalizationListener';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './localization.enum';
|
||||
@@ -0,0 +1,10 @@
|
||||
export enum LocalizationKey {
|
||||
dashboardHeaderCreateContent = 'dashboard.header.createContent',
|
||||
dashboardHeaderStartupLabel = 'dashboard.header.startup.label',
|
||||
panelActionsTitle = 'panel.actions.title',
|
||||
panelActionsOpenDashboard = 'panel.actions.openDashboard',
|
||||
panelActionsOpenPreview = 'panel.actions.openPreview',
|
||||
panelActionsStartServer = 'panel.actions.startServer',
|
||||
panelActionsStopServer = 'panel.actions.stopServer',
|
||||
panelActionsCreateContent = 'panel.actions.createContent'
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import { FEATURE_FLAG } from '../../constants/Features';
|
||||
import { Messenger } from '@estruyf/vscode/dist/client';
|
||||
import { GitAction } from './Git/GitAction';
|
||||
import { useMemo } from 'react';
|
||||
import * as l10n from "@vscode/l10n"
|
||||
import { LocalizationKey } from '../../localization';
|
||||
|
||||
export interface IBaseViewProps {
|
||||
settings: PanelSettings | undefined;
|
||||
@@ -88,15 +90,15 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({
|
||||
</FeatureFlag>
|
||||
|
||||
<FeatureFlag features={mode?.features || []} flag={FEATURE_FLAG.panel.actions}>
|
||||
<Collapsible id={`base_actions`} title="Actions">
|
||||
<Collapsible id={`base_actions`} title={l10n.t(LocalizationKey.panelActionsTitle)}>
|
||||
<div className={`base__actions`}>
|
||||
<button onClick={openDashboard}>Open dashboard</button>
|
||||
<button onClick={openDashboard}>{l10n.t(LocalizationKey.panelActionsOpenDashboard)}</button>
|
||||
<button onClick={openPreview} disabled={!settings?.preview?.host}>
|
||||
Open preview
|
||||
{l10n.t(LocalizationKey.panelActionsOpenPreview)}
|
||||
</button>
|
||||
<StartServerButton settings={settings} />
|
||||
|
||||
<button onClick={createContent}>Create new content</button>
|
||||
<button onClick={createContent}>{l10n.t(LocalizationKey.panelActionsCreateContent)}</button>
|
||||
|
||||
{customActions.map((script) => (
|
||||
<button key={script.title} onClick={() => runBulkScript(script)}>
|
||||
|
||||
@@ -3,6 +3,8 @@ import * as React from 'react';
|
||||
import { PanelSettings } from '../../models';
|
||||
import { CommandToCode } from '../CommandToCode';
|
||||
import useStartCommand from '../hooks/useStartCommand';
|
||||
import { LocalizationKey } from '../../localization';
|
||||
import * as l10n from "@vscode/l10n"
|
||||
|
||||
export interface IStartServerButtonProps {
|
||||
settings: PanelSettings | undefined;
|
||||
@@ -23,8 +25,8 @@ export const StartServerButton: React.FunctionComponent<IStartServerButtonProps>
|
||||
|
||||
return startCommand ? (
|
||||
<>
|
||||
<button onClick={() => startLocalServer(startCommand)}>Start server</button>
|
||||
<button onClick={() => stopLocalServer()}>Stop server</button>
|
||||
<button onClick={() => startLocalServer(startCommand)}>{l10n.t(LocalizationKey.panelActionsStartServer)}</button>
|
||||
<button onClick={() => stopLocalServer()}>{l10n.t(LocalizationKey.panelActionsStopServer)}</button>
|
||||
</>
|
||||
) : null;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Messenger } from '@estruyf/vscode/dist/client';
|
||||
import { EventData } from '@estruyf/vscode/dist/models';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { PanelSettingsAtom } from '../state';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
|
||||
export default function useMessages() {
|
||||
const [metadata, setMetadata] = useState<any>({});
|
||||
@@ -50,6 +51,11 @@ export default function useMessages() {
|
||||
case GeneralCommands.toWebview.setMode:
|
||||
setMode(message.payload);
|
||||
break;
|
||||
case GeneralCommands.toWebview.setLocalization:
|
||||
l10n.config({
|
||||
contents: message.payload
|
||||
})
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,6 +78,7 @@ export default function useMessages() {
|
||||
|
||||
Messenger.send(CommandToCode.getData);
|
||||
Messenger.send(CommandToCode.getMode);
|
||||
Messenger.send(GeneralCommands.toVSCode.getLocalization);
|
||||
|
||||
return () => {
|
||||
Messenger.unlisten(messageListener);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Uri, l10n } from 'vscode';
|
||||
import { Extension, Logger } from '../helpers';
|
||||
import { readFileAsync } from './readFileAsync';
|
||||
|
||||
export const getLocalizationFile = async () => {
|
||||
try {
|
||||
const localeFilePath =
|
||||
l10n.uri?.fsPath ||
|
||||
Uri.parse(`${Extension.getInstance().extensionPath}/l10n/bundle.l10n.json`).fsPath;
|
||||
|
||||
const fileContents = await readFileAsync(localeFilePath, 'utf-8');
|
||||
return fileContents;
|
||||
} catch (error) {
|
||||
Logger.error(`Failed to get the localization file: ${(error as Error).message}`);
|
||||
return '';
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user