i18nexus-cli 3.0.0 → 3.2.0

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
@@ -4,11 +4,16 @@
4
4
 
5
5
  ## New to i18nexus?
6
6
 
7
- [i18nexus](https://i18nexus.com) is a translation management web application designed for use with i18next. Learn more with this quick [Next.js walkthrough](https://i18nexus.com/nextjs-tutorial) or this [React.js walkthrough](https://i18nexus.com/react-tutorial).
7
+ [i18nexus](https://i18nexus.com) is a translation management web application designed for use with i18next, next-intl, and react-intl. Learn more with these quick tutorials:
8
+
9
+ - [next-i18next Walkthrough](https://i18nexus.com/tutorials/nextjs/next-i18next)
10
+ - [next-intl Walkthrough](https://i18nexus.com/tutorials/nextjs/next-intl)
11
+ - [react-i18next Walkthrough](https://i18nexus.com/tutorials/react/react-i18next)
12
+ - [react-intl Walkthrough](https://i18nexus.com/tutorials/react/react-intl)
8
13
 
9
14
  ## Who is this CLI meant for?
10
15
 
11
- - Developers who prefer to download and bundle their translation files with their app (especially useful for those who use SSR/SSG and libraries such as [next-i18next](https://github.com/isaachinman/next-i18next)).
16
+ - Developers who prefer to download and bundle their translation files with their app (especially useful for those who use SSR/SSG and libraries like Next.js).
12
17
  - Developers who wish to add, edit, or delete strings in their i18nexus project from the command line.
13
18
 
14
19
  ## Installation
@@ -19,7 +24,7 @@ npm install -g i18nexus-cli
19
24
 
20
25
  ## Environment Variables
21
26
 
22
- The commands below have options that can be set with environment variables. Since the majority of our users are using this package in the context of their web or mobile application, this package will load the `.env` file in the current working directory to check for i18nexus variables. If you would prefer not to load your `.env` file, you can run `export I18NEXUS_NO_DOT_ENV=true`.
27
+ The commands below have options that can be set with environment variables. Since the majority of our users are using this package in the context of their web application, this package will load the `.env` file in the current working directory to check for i18nexus variables. If you would prefer not to load your `.env` file, you can run `export I18NEXUS_NO_DOT_ENV=true`.
23
28
 
24
29
  ## Downloading your translations
25
30
 
@@ -27,7 +32,9 @@ The commands below have options that can be set with environment variables. Sinc
27
32
  i18nexus pull -k <PROJECT_API_KEY>
28
33
  ```
29
34
 
30
- The above snippet will download all of your latest translations to your current directory in the following structure:
35
+ The above snippet will download all of your latest translations to your current directory. Your translation files will be downloaded in a file structure based on the convention of your i18n library:
36
+
37
+ If your i18nexus project is set to `i18next`:
31
38
 
32
39
  ```
33
40
  .
@@ -39,7 +46,26 @@ The above snippet will download all of your latest translations to your current
39
46
  └── common.json
40
47
  ```
41
48
 
42
- This structure is i18next convention, and will work by default with [next-i18next](https://github.com/isaachinman/next-i18next).
49
+ If your i18nexus project is set to `next-intl`:
50
+
51
+ ```
52
+ .
53
+ └── messages
54
+ └── en.json
55
+ └── de.json
56
+ ```
57
+
58
+ If your i18nexus project is set to `react-intl`:
59
+
60
+ ```
61
+ .
62
+ └── messages
63
+ └── locales
64
+ ├── en
65
+ | └── common.json
66
+ └── de
67
+ └── common.json
68
+ ```
43
69
 
44
70
  If you wish to download your files to a different directory, you can use the `--path` option to specify your download destination. See all options below:
45
71
 
@@ -225,3 +251,28 @@ A personal access token that you have generated in your i18nexus account (Can al
225
251
 
226
252
  `--overwrite`
227
253
  If any keys already exist in the target namespace, overwrite the values with the imported values.
254
+
255
+ ## Adding new namespaces
256
+
257
+ `i18nexus add-namespace <namespaceTitle>`
258
+
259
+ ```sh
260
+ i18nexus add-namespace common -k <PROJECT_API_KEY> -t <YOUR_PERSONAL_ACCESS_TOKEN>
261
+ ```
262
+
263
+ The above snippet will create a new namespace in your i18nexus project with the title `common`.
264
+
265
+ ### Options
266
+
267
+ | Option | Required? |
268
+ | ------------------- | --------- |
269
+ | `--api-key` or `-k` | &#10004; |
270
+ | `--pat` or `-t` | &#10004; |
271
+
272
+ ### Notes
273
+
274
+ `--api-key`
275
+ Your project API key (Can also be set using environment variable `I18NEXUS_API_KEY`)
276
+
277
+ `--pat`
278
+ A personal access token that you have generated in your i18nexus account (Can also be set using environment variable `I18NEXUS_PERSONAL_ACCESS_TOKEN`)
package/bin/index.js CHANGED
@@ -7,6 +7,7 @@ const addString = require('../commands/addString');
7
7
  const updateString = require('../commands/updateString');
8
8
  const deleteString = require('../commands/deleteString');
9
9
  const importJson = require('../commands/importJson');
10
+ const addNamespace = require('../commands/addNamespace');
10
11
 
11
12
  // Using Next's env variable loader because
12
13
  // Next supports more than just one .env file
@@ -31,10 +32,9 @@ program
31
32
  'The version of the translations to be downloaded.',
32
33
  process.env.I18NEXUS_VERSION || 'latest'
33
34
  )
34
- .requiredOption(
35
+ .option(
35
36
  '-p, --path <path>',
36
- 'The path to the destination folder in which translation files will be downloaded',
37
- `${process.cwd()}/public/locales`
37
+ 'The path to the destination folder in which translation files will be downloaded'
38
38
  )
39
39
  .option(
40
40
  '--clean',
@@ -193,4 +193,26 @@ program
193
193
  });
194
194
  });
195
195
 
196
+ program
197
+ .command('add-namespace <namespaceTitle>')
198
+ .alias('a-ns')
199
+ .description('Add a new namespace to your project')
200
+ .requiredOption(
201
+ '-k, --api-key <apiKey>',
202
+ 'The API key for your project',
203
+ process.env.I18NEXUS_API_KEY
204
+ )
205
+ .requiredOption(
206
+ '-t, --pat <personalAccessToken>',
207
+ 'A personal access token generated for your account in i18nexus',
208
+ process.env.I18NEXUS_PERSONAL_ACCESS_TOKEN
209
+ )
210
+ .action((namespaceTitle, options) => {
211
+ addNamespace({
212
+ title: namespaceTitle,
213
+ apiKey: options.apiKey,
214
+ pat: options.pat
215
+ });
216
+ });
217
+
196
218
  program.parse(process.argv);
@@ -0,0 +1,31 @@
1
+ const colors = require('colors');
2
+ const handleError = require('../handleError');
3
+ const handleFetch = require('../handleFetch');
4
+ const baseUrl = require('../baseUrl');
5
+
6
+ const addNamespace = async opt => {
7
+ let url = `${baseUrl}/project_resources/namespaces.json`;
8
+
9
+ url += `?api_key=${opt.apiKey}`;
10
+
11
+ const response = await handleFetch(url, {
12
+ method: 'POST',
13
+ body: JSON.stringify({
14
+ title: opt.title
15
+ }),
16
+ headers: {
17
+ Authorization: `Bearer ${opt.pat}`,
18
+ 'Content-Type': 'application/json'
19
+ }
20
+ });
21
+
22
+ if (response.status !== 200) {
23
+ return handleError(response);
24
+ }
25
+
26
+ await response.json();
27
+
28
+ console.log(colors.green(`New namespace added: "${opt.title}"`));
29
+ };
30
+
31
+ module.exports = addNamespace;
package/commands/pull.js CHANGED
@@ -3,6 +3,7 @@ const colors = require('colors');
3
3
  const handleError = require('../handleError');
4
4
  const handleFetch = require('../handleFetch');
5
5
  const baseUrl = require('../baseUrl');
6
+ const getProject = require('../getProject');
6
7
 
7
8
  const cleanDirectory = path => {
8
9
  if (!fs.existsSync(path)) {
@@ -22,9 +23,30 @@ const cleanDirectory = path => {
22
23
  };
23
24
 
24
25
  const pull = async opt => {
25
- const usingVersion = opt.version !== 'latest';
26
+ let path = opt.path;
27
+
28
+ const project = await getProject(opt.apiKey);
29
+
30
+ const projectLibrary = project.library;
26
31
 
27
- console.log(baseUrl);
32
+ if (!path) {
33
+ if (!projectLibrary) {
34
+ console.log(
35
+ colors.red(
36
+ 'There was a problem fetching your translations. Please try again in a moment.'
37
+ )
38
+ );
39
+ return process.exit(1);
40
+ }
41
+
42
+ if (projectLibrary === 'i18next') {
43
+ path = `${process.cwd()}/public/locales`;
44
+ } else {
45
+ path = `${process.cwd()}/messages`;
46
+ }
47
+ }
48
+
49
+ const usingVersion = opt.version !== 'latest';
28
50
 
29
51
  let url = usingVersion
30
52
  ? `https://cdn.i18nexus.com/versions/${opt.version}/translations.json`
@@ -32,7 +54,7 @@ const pull = async opt => {
32
54
 
33
55
  url += `?api_key=${opt.apiKey}`;
34
56
 
35
- console.log(`Downloading translations to ${opt.path}...`);
57
+ console.log(`Downloading translations to ${path}...`);
36
58
 
37
59
  const response = await handleFetch(url);
38
60
 
@@ -48,19 +70,30 @@ const pull = async opt => {
48
70
  const translations = await response.json();
49
71
 
50
72
  if (opt.clean) {
51
- cleanDirectory(opt.path);
73
+ cleanDirectory(path);
52
74
  }
53
75
 
54
- for (let lng in translations) {
55
- const lngFilePath = `${opt.path}/${lng}`;
56
- fs.mkdirSync(lngFilePath, { recursive: true });
76
+ if (projectLibrary === 'next-intl') {
77
+ for (let lng in translations) {
78
+ fs.mkdirSync(path, { recursive: true });
57
79
 
58
- for (let namespace in translations[lng]) {
59
80
  fs.writeFileSync(
60
- `${lngFilePath}/${namespace}.json`,
61
- JSON.stringify(translations[lng][namespace])
81
+ `${path}/${lng}.json`,
82
+ JSON.stringify(translations[lng])
62
83
  );
63
84
  }
85
+ } else {
86
+ for (let lng in translations) {
87
+ const lngFilePath = `${path}/${lng}`;
88
+ fs.mkdirSync(lngFilePath, { recursive: true });
89
+
90
+ for (let namespace in translations[lng]) {
91
+ fs.writeFileSync(
92
+ `${lngFilePath}/${namespace}.json`,
93
+ JSON.stringify(translations[lng][namespace])
94
+ );
95
+ }
96
+ }
64
97
  }
65
98
 
66
99
  console.log(colors.green('Translations downloaded successfully.'));
package/getProject.js ADDED
@@ -0,0 +1,20 @@
1
+ const handleError = require('./handleError');
2
+ const handleFetch = require('./handleFetch');
3
+ const baseUrl = require('./baseUrl');
4
+
5
+ const getProject = async apiKey => {
6
+ const url = `${baseUrl}/project_resources/project.json?api_key=${apiKey}`;
7
+
8
+ const response = await handleFetch(url);
9
+
10
+ if (response.status !== 200) {
11
+ return handleError(
12
+ response,
13
+ 'There was a problem fetching your translations. Please try again in a moment.'
14
+ );
15
+ }
16
+
17
+ return response.json();
18
+ };
19
+
20
+ module.exports = getProject;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18nexus-cli",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "Command line interface (CLI) for accessing the i18nexus API",
5
5
  "main": "index.js",
6
6
  "bin": {