From d6bcfe2ea25b0efd7ecb9d56dc4c926d08f551c7 Mon Sep 17 00:00:00 2001 From: Grégoire Aubert Date: Wed, 23 Oct 2024 15:59:45 +0200 Subject: SONAR-23475 Provide up to date l10n files when using webapp proxy server --- server/sonar-web/.eslintrc | 9 ++- .../config/vite-dev-server-l10n-plugin.mjs | 84 ++++++++++++++++++++++ server/sonar-web/scripts/utils.js | 75 ------------------- server/sonar-web/vite.config.mjs | 3 +- 4 files changed, 93 insertions(+), 78 deletions(-) create mode 100644 server/sonar-web/config/vite-dev-server-l10n-plugin.mjs delete mode 100644 server/sonar-web/scripts/utils.js diff --git a/server/sonar-web/.eslintrc b/server/sonar-web/.eslintrc index 09c65f0aba4..71a90d503cc 100644 --- a/server/sonar-web/.eslintrc +++ b/server/sonar-web/.eslintrc @@ -6,7 +6,12 @@ "eslint-plugin-local-rules" ], "ignorePatterns": [ - "config/jest/**/*.ts", + "babel.config.js", + "jest.config.js", + "vite.config.mjs", + "tailwind*.js", + "script/**/*", + "config/**/*", "eslint-local-rules/**/*" ], "root": true, @@ -100,4 +105,4 @@ } ] } -} \ No newline at end of file +} diff --git a/server/sonar-web/config/vite-dev-server-l10n-plugin.mjs b/server/sonar-web/config/vite-dev-server-l10n-plugin.mjs new file mode 100644 index 00000000000..4e53c09ded8 --- /dev/null +++ b/server/sonar-web/config/vite-dev-server-l10n-plugin.mjs @@ -0,0 +1,84 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import fs from 'node:fs'; +import path from 'node:path'; +import { promisify } from 'node:util'; + +const readFileAsync = promisify(fs.readFile); + +const l10nFilePath = '../../../sonar-core/src/main/resources/org/sonar/l10n/core.properties'; + +const extensionsL10nFilepaths = [ + '../../../private/core-extension-enterprise-server/src/main/resources/org/sonar/l10n/governance.properties', + '../../../private/core-extension-license/src/main/resources/org/sonar/l10n/license.properties', + '../../../private/core-extension-developer-server/src/main/resources/org/sonar/l10n/developer-server.properties', + '../../../private/core-extension-securityreport/src/main/resources/org/sonar/l10n/securityreport.properties', +]; + +const STATUS_OK = 200; +const STATUS_ERROR = 500; + +function getFileMessage(filename) { + return readFileAsync(path.resolve(__dirname, filename), 'utf-8').then( + (content) => { + const messages = {}; + const lines = content.split('\n'); + lines.forEach((line) => { + const parts = line.split('='); + if (parts.length > 1) { + messages[parts[0]] = parts.slice(1).join('='); + } + }); + return messages; + }, + () => ({}), + ); +} + +function getMessages() { + return Promise.all( + [l10nFilePath, ...extensionsL10nFilepaths].map((filename) => getFileMessage(filename)), + ).then((filesMessages) => filesMessages.reduce((acc, messages) => ({ ...acc, ...messages }), {})); +} + +// this is a custom l10n-dev-server when proxying locally against another environment so that +// we don't need to rebuild the server when changing the l10n files +export const viteDevServerL10nPlugin = () => { + return { + name: 'l10n-dev-server', + apply: 'serve', + configureServer(server) { + const app = server.middlewares; + app.use('/api/l10n', (_req, res) => { + getMessages() + .then((messages) => { + res.writeHead(STATUS_OK, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ effectiveLocale: 'en', messages })); + }) + .catch((e) => { + console.error(e); + res.writeHead(STATUS_ERROR); + res.end(e); + }); + }); + }, + }; +}; diff --git a/server/sonar-web/scripts/utils.js b/server/sonar-web/scripts/utils.js deleted file mode 100644 index 5e4534fbddd..00000000000 --- a/server/sonar-web/scripts/utils.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -const fs = require('fs'); -const path = require('path'); -const { promisify } = require('util'); - -const readFileAsync = promisify(fs.readFile); - -const l10nFilePath = '../../../sonar-core/src/main/resources/org/sonar/l10n/core.properties'; - -const extensionsL10nFilepaths = [ - '../../../private/core-extension-enterprise-server/src/main/resources/org/sonar/l10n/governance.properties', - '../../../private/core-extension-license/src/main/resources/org/sonar/l10n/license.properties', - '../../../private/core-extension-developer-server/src/main/resources/org/sonar/l10n/developer-server.properties', - '../../../private/core-extension-securityreport/src/main/resources/org/sonar/l10n/securityreport.properties', -]; - -const STATUS_OK = 200; -const STATUS_ERROR = 500; - -function getFileMessage(filename) { - return readFileAsync(path.resolve(__dirname, filename), 'utf-8').then( - (content) => { - const messages = {}; - const lines = content.split('\n'); - lines.forEach((line) => { - const parts = line.split('='); - if (parts.length > 1) { - messages[parts[0]] = parts.slice(1).join('='); - } - }); - return messages; - }, - () => ({}), - ); -} - -function getMessages() { - return Promise.all( - [l10nFilePath, ...extensionsL10nFilepaths].map((filename) => getFileMessage(filename)), - ).then((filesMessages) => filesMessages.reduce((acc, messages) => ({ ...acc, ...messages }), {})); -} - -function handleL10n(res) { - getMessages() - .then((messages) => { - res.writeHead(STATUS_OK, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ effectiveLocale: 'en', messages })); - }) - .catch((e) => { - console.error(e); - res.writeHead(STATUS_ERROR); - res.end(e); - }); -} - -module.exports = { handleL10n }; diff --git a/server/sonar-web/vite.config.mjs b/server/sonar-web/vite.config.mjs index 715553c3ace..5fcf039cacb 100644 --- a/server/sonar-web/vite.config.mjs +++ b/server/sonar-web/vite.config.mjs @@ -32,6 +32,7 @@ import requireTransform from 'vite-plugin-require-transform'; import babelConfig from './babel.config'; import { ALLOWED_LICENSES, ALLOWED_LICENSE_TEXT, generateLicenseText } from './config/license'; import { viteDevServerHtmlPlugin } from './config/vite-dev-server-html-plugin.mjs'; +import { viteDevServerL10nPlugin } from './config/vite-dev-server-l10n-plugin.mjs'; import packageJson from './package.json'; const DEFAULT_DEV_SERVER_PORT = 3000; @@ -39,7 +40,6 @@ const DEFAULT_WS_PROXY_PORT = 3010; const port = process.env.PORT || DEFAULT_DEV_SERVER_PORT; const proxyTarget = (process.env.PROXY || 'http://localhost:9000').replace(/\/$/, ''); -const isProxied = !proxyTarget.includes('localhost'); const isProduction = process.env.NODE_ENV === 'production'; const analyzeBundle = process.env.BUNDLE_ANALYSIS || false; @@ -165,6 +165,7 @@ export default ({ mode }) => { // More Info: https://www.npmjs.com/package/babel-plugin-macros macrosPlugin(), viteDevServerHtmlPlugin(), + viteDevServerL10nPlugin(), analyzeBundle && visualizer({ filename: './build/bundle-analyzer.html', -- cgit v1.2.3