@localazy/strapi-plugin 0.1.18 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,57 +1,38 @@
1
+ ## Quick Installation
2
+
3
+ ```
4
+ npx @localazy/strapi-plugin
5
+ ```
6
+
1
7
  ## The Official Strapi Localization Plugin by Localazy
2
8
 
3
9
  Strapi localization doesn't have to be a headache! Install the Strapi localization plugin and seamlessly translate your content into multiple languages with [Localazy](https://localazy.com).
4
10
 
5
11
  ### Manage your multilingual content with ease
12
+
6
13
  1. [Sign up](https://localazy.com/register) & Upload your content to Localazy.
7
14
  2. Translate your content with machine translation assistance, or let the Localazy [Continuous Localization Team](https://localazy.com/blog/guide-localazy-translation-services) translate your content for you. You can also quickly pre-translate everything in bulk or invite your translators.
8
15
  3. Download translated content back to Strapi and feel the seamless experience of multilingual content management.
9
16
 
10
17
  📰 Learn more in the [Strapi + Localazy tutorial](https://localazy.com/blog/how-to-strapi-localization-with-localazy#getting-started-with-strapi-localization).
11
18
 
12
- ## Setup
13
-
14
- ### Install the plugin via NPM
19
+ ## Installation & Setup
15
20
 
16
21
  The plugin is available on [NPM](https://www.npmjs.com/package/@localazy/strapi-plugin).
17
- You can also follow the installation commands located in your Strapi project Marketplace. This is the recommended approach.
18
-
19
- ```
20
- npm install @localazy/strapi-plugin
21
- ```
22
-
23
- ### Use the plugin in a clean project locally
24
-
25
- Besides installing the plugin via `npm`, you can also use it in a project locally. Assuming you have a (clean) Strapi project set up, do:
26
-
27
- 1. Copy the whole contents.
28
- 2. Paste it into `./src/plugin/localazy` folder of your project (path from project root).
29
- 3. Create `./config/plugins.js` file (path from project root).
30
- 4. Add the following contents to `./config/plugins.js` file:
22
+ You can also follow the installation commands located in your Strapi project Marketplace or [Strapi Marketplace > Localazy](https://market.strapi.io/plugins/@localazy-strapi-plugin) itself. This is the recommended approach.
31
23
 
32
24
  ```
33
- module.exports = {
34
- localazy: {
35
- enabled: true,
36
- resolve: "./src/plugins/localazy",
37
- config: {
38
- default: () => {},
39
- validator: () => {},
40
- },
41
- },
42
- };
25
+ npx @localazy/strapi-plugin
43
26
  ```
44
27
 
45
- 5. Run the project. The plugin will be available in the admin.
46
-
47
- ### Tests
48
-
49
- To run tests, run the `npm run test` command. To watch tests, run the `npm run test:watch` command.
28
+ Note: Localazy plugin requires an updated Webpack configuration of your Strapi project. Follow the instructions in the console output during the installation process. Steps are also available in the [Install plugin via NPM](https://localazy.com/docs/strapi/strapi-plugin-introduction-installation#install-plugin-via-npm) section of the Localazy Docs.
50
29
 
51
30
  ## Additional Resources
31
+
52
32
  - Localazy Docs: [Introduction to Strapi](https://localazy.com/docs/strapi/strapi-plugin-introduction-installation)
53
33
  - Localazy Blog: [Articles about the Strapi plugin](https://localazy.com/tags/strapi)
54
34
 
55
35
  ## Support
36
+
56
37
  - If you encounter any issues or have questions, please contact us at [team@localazy.com](mailto:team@localazy.com).
57
38
  - Join the [Localazy Discussion Forum](https://discuss.localazy.com/) to discuss all things localization.
@@ -0,0 +1 @@
1
+ export const LOCALAZY_PLUGIN_CHANNEL = "localazy-plugin";
@@ -0,0 +1,4 @@
1
+ export const UPLOAD_EVENT = "upload";
2
+ export const UPLOAD_FINISHED_EVENT = "upload:finished";
3
+ export const DOWNLOAD_EVENT = "download";
4
+ export const DOWNLOAD_FINISHED_EVENT = "download:finished";
@@ -0,0 +1,25 @@
1
+ import SocketIoClient from "socket.io-client";
2
+ import { LOCALAZY_PLUGIN_CHANNEL } from "../constants/channels";
3
+
4
+
5
+ export default class AlertsService {
6
+ _client;
7
+
8
+ _streamIdentifier;
9
+
10
+ constructor() {
11
+ this._client = SocketIoClient.connect(process.env.STRAPI_ADMIN_BACKEND_URL);
12
+ }
13
+
14
+ setStreamIdentifier(streamIdentifier) {
15
+ this._streamIdentifier = streamIdentifier;
16
+ }
17
+
18
+ subscribe(channel = null) {
19
+ this._client.emit("subscribe", channel || LOCALAZY_PLUGIN_CHANNEL);
20
+ }
21
+
22
+ on(event, callback) {
23
+ this._client.on(`${event}:${this._streamIdentifier}`, callback);
24
+ }
25
+ }
@@ -20,4 +20,6 @@ export default {
20
20
  ui_languages: "Select languages to download",
21
21
  ui_languages_info: "Select translations of which languages wil be downloaded from Localazy",
22
22
  ui_languages_placeholder: "Download all languages",
23
+ download_in_progress: "Download in progress...",
24
+ to_see_to_progress: "To see the progress information, do not leave this page.",
23
25
  };
@@ -0,0 +1,12 @@
1
+ import AlertsService from "../../alerts/services/alerts-service";
2
+ import { DOWNLOAD_EVENT, DOWNLOAD_FINISHED_EVENT } from "../../alerts/constants/events";
3
+
4
+ export default class DownloadAlertsService extends AlertsService {
5
+ onDownload(callback) {
6
+ this.on(DOWNLOAD_EVENT, callback);
7
+ }
8
+
9
+ onDownloadFinished(callback) {
10
+ this.on(DOWNLOAD_FINISHED_EVENT, callback);
11
+ }
12
+ }
@@ -15,4 +15,6 @@ export default {
15
15
  upload_success: "Content successfully imported to the Localazy project.",
16
16
  upload_failed:
17
17
  "Upload partially failed, please check the report for details...",
18
+ upload_in_progress: "Upload in progress...",
19
+ to_see_to_progress: "To see the progress information, do not leave this page.",
18
20
  };
@@ -0,0 +1,12 @@
1
+ import AlertsService from "../../alerts/services/alerts-service";
2
+ import { UPLOAD_EVENT, UPLOAD_FINISHED_EVENT } from "../../alerts/constants/events";
3
+
4
+ export default class UploadAlertsService extends AlertsService {
5
+ onUpload(callback) {
6
+ this.on(UPLOAD_EVENT, callback);
7
+ }
8
+
9
+ onUploadFinished(callback) {
10
+ this.on(UPLOAD_FINISHED_EVENT, callback);
11
+ }
12
+ }
@@ -24,6 +24,10 @@ import PluginSettingsService from "../../modules/plugin-settings/services/plugin
24
24
  import { PLUGIN_ROUTES } from "../../modules/@common/utils/redirect-to-plugin-route";
25
25
  import LanguagesSelector from "../../modules/@common/components/LanguagesSelector";
26
26
  import ProjectService from "../../modules/@common/services/project-service";
27
+ import DownloadAlertsService from "../../modules/localazy-download/services/download-alerts-service";
28
+
29
+ const downloadAlertsService = new DownloadAlertsService();
30
+ downloadAlertsService.subscribe();
27
31
 
28
32
  function Download(props) {
29
33
  const { t } = useTranslation();
@@ -36,7 +40,10 @@ function Download(props) {
36
40
  const [localesIncompatible, setLocalesIncompatible] = useState(false);
37
41
  const [showDownloadFinishedModal, setshowDownloadFinishedModal] =
38
42
  useState(false);
39
- const [downloadResult, setDownloadResult] = useState({});
43
+ const [downloadResult, setDownloadResult] = useState({
44
+ success: false,
45
+ report: [],
46
+ });
40
47
  const [isDownloading, setIsDownloading] = useState(false);
41
48
 
42
49
  /**
@@ -72,8 +79,34 @@ function Download(props) {
72
79
 
73
80
  const onDownloadClick = async () => {
74
81
  setIsDownloading(true);
82
+ setshowDownloadFinishedModal(false);
83
+ setDownloadResult({
84
+ success: false,
85
+ report: [],
86
+ });
75
87
  const result = await LocalazyDownloadService.download();
76
- setDownloadResult(result);
88
+ const { streamIdentifier } = result;
89
+ downloadAlertsService.setStreamIdentifier(streamIdentifier);
90
+ downloadAlertsService.onDownload((data) => {
91
+ setDownloadResult((old) => ({
92
+ success: data.success,
93
+ report: [
94
+ ...old.report || [],
95
+ data.message,
96
+ ],
97
+ }));
98
+ });
99
+ downloadAlertsService.onDownloadFinished((data) => {
100
+ setDownloadResult((old) => ({
101
+ success: data.success,
102
+ report: [
103
+ ...old.report || [],
104
+ data.message,
105
+ ],
106
+ }));
107
+ setIsDownloading(false);
108
+ setshowDownloadFinishedModal(true);
109
+ });
77
110
 
78
111
  // track download
79
112
  ProductAnalyticsService.trackDownloadToStrapi(
@@ -83,9 +116,6 @@ function Download(props) {
83
116
  "Target Languages Codes": "all",
84
117
  }
85
118
  );
86
-
87
- setIsDownloading(false);
88
- setshowDownloadFinishedModal(true);
89
119
  };
90
120
 
91
121
  useEffect(() => {
@@ -200,6 +230,16 @@ function Download(props) {
200
230
  </Alert>
201
231
  </Box>
202
232
  )}
233
+ {isDownloading && (
234
+ <Box marginTop={4} marginBottom={4}>
235
+ <Alert
236
+ title={t("download.download_in_progress")}
237
+ variant="warning"
238
+ >
239
+ {t("download.to_see_to_progress")}
240
+ </Alert>
241
+ </Box>
242
+ )}
203
243
  {localesIncompatible && (
204
244
  <Box marginTop={4} marginBottom={4}>
205
245
  <Alert
@@ -24,9 +24,13 @@ import redirectToPluginRoute, {
24
24
  import { getLocalazyIdentity } from "../../state/localazy-identity";
25
25
  import ProductAnalyticsService from "../../modules/@common/services/product-analytics-service";
26
26
  import PluginSettingsService from "../../modules/plugin-settings/services/plugin-settings-service";
27
+ import UploadAlertsService from "../../modules/localazy-upload/services/upload-alerts-service";
27
28
 
28
29
  import "../../i18n";
29
30
 
31
+ const uploadAlertsService = new UploadAlertsService();
32
+ uploadAlertsService.subscribe();
33
+
30
34
  function Upload(props) {
31
35
  const { t } = useTranslation();
32
36
 
@@ -37,7 +41,10 @@ function Upload(props) {
37
41
  const [modelChanged, setModelChanged] = useState(false);
38
42
  const [localesIncompatible, setLocalesIncompatible] = useState(false);
39
43
  const [showUploadFinishedModal, setShowUploadFinishedModal] = useState(false);
40
- const [uploadResult, setUploadResult] = useState({});
44
+ const [uploadResult, setUploadResult] = useState({
45
+ success: false,
46
+ report: [],
47
+ });
41
48
  const [isUploading, setIsUploading] = useState(false);
42
49
  const [strapiDefaultLocale, setStrapiDefaultLocale] = useState(null);
43
50
  const [localazySourceLanguage, setLocalazySourceLanguage] = useState(null);
@@ -51,8 +58,34 @@ function Upload(props) {
51
58
 
52
59
  const onUploadClick = async () => {
53
60
  setIsUploading(true);
61
+ setShowUploadFinishedModal(false);
62
+ setUploadResult({
63
+ success: false,
64
+ report: [],
65
+ });
54
66
  const result = await LocalazyUploadService.upload();
55
- setUploadResult(result);
67
+ const { streamIdentifier } = result;
68
+ uploadAlertsService.setStreamIdentifier(streamIdentifier);
69
+ uploadAlertsService.onUpload((data) => {
70
+ setUploadResult((old) => ({
71
+ success: data.success,
72
+ report: [
73
+ ...old.report || [],
74
+ data.message,
75
+ ],
76
+ }));
77
+ });
78
+ uploadAlertsService.onUploadFinished((data) => {
79
+ setUploadResult((old) => ({
80
+ success: data.success,
81
+ report: [
82
+ ...old.report || [],
83
+ data.message,
84
+ ],
85
+ }));
86
+ setIsUploading(false);
87
+ setShowUploadFinishedModal(true);
88
+ });
56
89
 
57
90
  // track upload
58
91
  ProductAnalyticsService.trackUploadToLocalazy(
@@ -62,9 +95,6 @@ function Upload(props) {
62
95
  "Source Language Code": localazySourceLanguage.code,
63
96
  }
64
97
  );
65
-
66
- setIsUploading(false);
67
- setShowUploadFinishedModal(true);
68
98
  };
69
99
 
70
100
  useEffect(() => {
@@ -162,6 +192,16 @@ function Upload(props) {
162
192
  </Alert>
163
193
  </Box>
164
194
  )}
195
+ {isUploading && (
196
+ <Box marginTop={4} marginBottom={4}>
197
+ <Alert
198
+ title={t("upload.upload_in_progress")}
199
+ variant="warning"
200
+ >
201
+ {t("upload.to_see_to_progress")}
202
+ </Alert>
203
+ </Box>
204
+ )}
165
205
  {localesIncompatible && (
166
206
  <Box marginTop={4} marginBottom={4}>
167
207
  <Alert
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'url';
5
+ import fs from 'fs-extra';
6
+ import chalk from 'chalk';
7
+ import ora from 'ora';
8
+ import shell from 'shelljs';
9
+ import { createRequire } from 'module';
10
+
11
+ // To prevent node experimental features warning after `import(package.json)` require is used instead.
12
+ const require = createRequire(import.meta.url);
13
+ const pkg = require('../package.json');
14
+
15
+ // https://patorjk.com/software/taag/#p=display&h=1&v=1&f=Sub-Zero&t=Localazy
16
+ const banner = chalk.blue(`
17
+ __ ______ ______ ______ __ ______ ______ __ __
18
+ /\\ \\ /\\ __ \\ /\\ ___\\ /\\ __ \\ /\\ \\ /\\ __ \\ /\\___ \\ /\\ \\_\\ \\
19
+ \\ \\ \\____\\ \\ \\/\\ \\\\ \\ \\____\\ \\ __ \\\\ \\ \\____\\ \\ __ \\\\/_/ /__\\ \\____ \\
20
+ \\ \\_____\\\\ \\_____\\\\ \\_____\\\\ \\_\\ \\_\\\\ \\_____\\\\ \\_\\ \\_\\ /\\_____\\\\/\\_____\\
21
+ \\/_____/ \\/_____/ \\/_____/ \\/_/\\/_/ \\/_____/ \\/_/\\/_/ \\/_____/ \\/_____/
22
+ `);
23
+ const name = `${chalk.bold.green(pkg.name)}`;
24
+ const version = `${chalk.grey(`@${pkg.version}`)}`;
25
+ const exampleFileName = 'webpack.config.localazy-strapi-plugin.example.js';
26
+ const file = `${chalk.bold.green(exampleFileName)}`;
27
+ const __filename = fileURLToPath(import.meta.url);
28
+ const __dirname = path.dirname(__filename);
29
+ const template = (await fs.readFile(path.join(__dirname, 'webpack.example.js'))).toString();
30
+ const installSpinner = ora();
31
+
32
+ const install = () => new Promise((resolve, reject) => {
33
+ try {
34
+ shell.exec(`npm install ${pkg.name}`, { silent: true }, () => {
35
+ resolve();
36
+ });
37
+ } catch (err) {
38
+ reject(err);
39
+ }
40
+ });
41
+
42
+ const updateConfig = () => new Promise((resolve, reject) => {
43
+ try {
44
+ shell.exec(`echo "${template}" > src/admin/${exampleFileName}`, { silent: true }, () => {
45
+ resolve();
46
+ });
47
+ } catch (err) {
48
+ reject(err);
49
+ }
50
+ });
51
+
52
+ console.log(banner);
53
+
54
+ installSpinner.start(`Installing ${name}${version}`);
55
+ await install();
56
+ installSpinner.succeed();
57
+
58
+ installSpinner.start(`Creating example ${file} file in ${chalk.bold.green("src/admin")} folder`);
59
+ await updateConfig();
60
+ installSpinner.succeed();
61
+ installSpinner.succeed(`To run the plugin, you need to update your webpack config in ${chalk.bold.green("src/admin/webpack.config.js")} file`);
62
+ installSpinner.succeed(`Don't forget to build the admin panel with ${chalk.bold.green("npm run build")} command`);
@@ -0,0 +1,30 @@
1
+ module.exports = (config, webpack) => {
2
+ /**
3
+ * This is an example of how to extend webpack config in order to use Localazy Strapi Plugin.
4
+ * Because Strapi is using Webpack 5, it is necessary to disable some Node.js polyfills in the Strapi monorepo.
5
+ *
6
+ * If your webpack config does not exist, create one.
7
+ */
8
+
9
+ return {
10
+ ...config,
11
+ resolve: {
12
+ ...config.resolve,
13
+ fallback: {
14
+ ...config.resolve.fallback,
15
+ crypto: false,
16
+ http: false,
17
+ fs: false,
18
+ zlib: false,
19
+ https: false,
20
+ stream: false,
21
+ path: false,
22
+ timers: false,
23
+ tls: false,
24
+ net: false,
25
+ url: false,
26
+ querystring: false,
27
+ },
28
+ }
29
+ };
30
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localazy/strapi-plugin",
3
- "version": "0.1.18",
3
+ "version": "0.2.1",
4
4
  "description": "The official Strapi Plugin by Localazy.",
5
5
  "strapi": {
6
6
  "name": "localazy",
@@ -24,6 +24,7 @@
24
24
  "email": "team@localazy.com",
25
25
  "url": "https://localazy.com"
26
26
  },
27
+ "bin": "./install/index.mjs",
27
28
  "repository": {
28
29
  "type": "git",
29
30
  "url": "git@github.com:localazy/strapi-plugin.git"
@@ -40,13 +41,19 @@
40
41
  "dependencies": {
41
42
  "@david-vaclavek/deep-keys": "^0.5.0",
42
43
  "@localazy/ts-api": "^1.0.13",
44
+ "chalk": "^5.3.0",
45
+ "fs-extra": "^11.1.1",
43
46
  "i18next": "^22.4.9",
44
47
  "isomorphic-fetch": "^3.0.0",
45
48
  "js-cookie": "^3.0.1",
46
49
  "lodash": "^4.17.21",
47
50
  "module-alias": "^2.2.2",
51
+ "ora": "^7.0.1",
48
52
  "react-hooks-global-state": "^2.1.0",
49
53
  "react-i18next": "^12.1.4",
54
+ "shelljs": "^0.8.5",
55
+ "socket.io-client": "^4.7.2",
56
+ "strapio": "^3.0.2",
50
57
  "styled-components": "^5.3.6"
51
58
  },
52
59
  "devDependencies": {
@@ -57,4 +57,7 @@ module.exports = ({ strapi }) => {
57
57
  break;
58
58
  }
59
59
  });
60
+ process.nextTick(() => {
61
+ strapi.StrapIO = (require('strapio'))(strapi);
62
+ });
60
63
  };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ LOCALAZY_PLUGIN_CHANNEL: "localazy-plugin",
3
+ };
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ UPLOAD_EVENT: "upload",
3
+ UPLOAD_FINISHED_EVENT: "upload:finished",
4
+ DOWNLOAD_EVENT: "download",
5
+ DOWNLOAD_FINISHED_EVENT: "download:finished",
6
+ };