i18nexus-cli 3.1.0 → 3.3.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 +50 -11
- package/bin/index.js +2 -3
- package/commands/pull.js +56 -10
- package/getProject.js +20 -0
- package/package.json +1 -1
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
|
|
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
|
|
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
|
|
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,11 @@ 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
|
|
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
|
+
### Default download path:
|
|
38
|
+
|
|
39
|
+
If your i18nexus project is set to **`i18next`**:
|
|
31
40
|
|
|
32
41
|
```
|
|
33
42
|
.
|
|
@@ -39,18 +48,48 @@ The above snippet will download all of your latest translations to your current
|
|
|
39
48
|
└── common.json
|
|
40
49
|
```
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
If your i18nexus project is set to **`i18next`** and the CLI detects you're using **Next.js + App Router**:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
.
|
|
55
|
+
└── locales
|
|
56
|
+
├── en
|
|
57
|
+
| └── common.json
|
|
58
|
+
└── de
|
|
59
|
+
└── common.json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If your i18nexus project is set to **`next-intl`**:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
.
|
|
66
|
+
└── messages
|
|
67
|
+
└── en.json
|
|
68
|
+
└── de.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If your i18nexus project is set to **`react-intl`**:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
.
|
|
75
|
+
└── messages
|
|
76
|
+
└── locales
|
|
77
|
+
├── en
|
|
78
|
+
| └── common.json
|
|
79
|
+
└── de
|
|
80
|
+
└── common.json
|
|
81
|
+
```
|
|
43
82
|
|
|
44
83
|
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
84
|
|
|
46
85
|
### Options
|
|
47
86
|
|
|
48
|
-
| Option | Default value
|
|
49
|
-
| ------------------- |
|
|
50
|
-
| `--api-key` or `-k` |
|
|
51
|
-
| `--path` or `-p` |
|
|
52
|
-
| `--ver` or `-v` | `latest`
|
|
53
|
-
| `--clean` | `false`
|
|
87
|
+
| Option | Default value |
|
|
88
|
+
| ------------------- | ------------- |
|
|
89
|
+
| `--api-key` or `-k` | |
|
|
90
|
+
| `--path` or `-p` | (See above) |
|
|
91
|
+
| `--ver` or `-v` | `latest` |
|
|
92
|
+
| `--clean` | `false` |
|
|
54
93
|
|
|
55
94
|
### Notes
|
|
56
95
|
|
package/bin/index.js
CHANGED
|
@@ -32,10 +32,9 @@ program
|
|
|
32
32
|
'The version of the translations to be downloaded.',
|
|
33
33
|
process.env.I18NEXUS_VERSION || 'latest'
|
|
34
34
|
)
|
|
35
|
-
.
|
|
35
|
+
.option(
|
|
36
36
|
'-p, --path <path>',
|
|
37
|
-
'The path to the destination folder in which translation files will be downloaded'
|
|
38
|
-
`${process.cwd()}/public/locales`
|
|
37
|
+
'The path to the destination folder in which translation files will be downloaded'
|
|
39
38
|
)
|
|
40
39
|
.option(
|
|
41
40
|
'--clean',
|
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,43 @@ const cleanDirectory = path => {
|
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
const pull = async opt => {
|
|
25
|
-
|
|
26
|
+
let path = opt.path;
|
|
27
|
+
|
|
28
|
+
const project = await getProject(opt.apiKey);
|
|
29
|
+
|
|
30
|
+
const projectLibrary = project.library;
|
|
26
31
|
|
|
27
|
-
|
|
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
|
+
const hasAppDir =
|
|
44
|
+
fs.existsSync(`${process.cwd()}/app`) ||
|
|
45
|
+
fs.existsSync(`${process.cwd()}/src/app`);
|
|
46
|
+
const usingAppRouter =
|
|
47
|
+
hasAppDir &&
|
|
48
|
+
(fs.existsSync(`${process.cwd()}/.next`) ||
|
|
49
|
+
fs.existsSync(`${process.cwd()}/next.config.js`) ||
|
|
50
|
+
fs.existsSync(`${process.cwd()}/next.config.ts`));
|
|
51
|
+
|
|
52
|
+
if (usingAppRouter) {
|
|
53
|
+
path = `${process.cwd()}/locales`;
|
|
54
|
+
} else {
|
|
55
|
+
path = `${process.cwd()}/public/locales`;
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
path = `${process.cwd()}/messages`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const usingVersion = opt.version !== 'latest';
|
|
28
63
|
|
|
29
64
|
let url = usingVersion
|
|
30
65
|
? `https://cdn.i18nexus.com/versions/${opt.version}/translations.json`
|
|
@@ -32,7 +67,7 @@ const pull = async opt => {
|
|
|
32
67
|
|
|
33
68
|
url += `?api_key=${opt.apiKey}`;
|
|
34
69
|
|
|
35
|
-
console.log(`Downloading translations to ${
|
|
70
|
+
console.log(`Downloading translations to ${path}...`);
|
|
36
71
|
|
|
37
72
|
const response = await handleFetch(url);
|
|
38
73
|
|
|
@@ -48,19 +83,30 @@ const pull = async opt => {
|
|
|
48
83
|
const translations = await response.json();
|
|
49
84
|
|
|
50
85
|
if (opt.clean) {
|
|
51
|
-
cleanDirectory(
|
|
86
|
+
cleanDirectory(path);
|
|
52
87
|
}
|
|
53
88
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
89
|
+
if (projectLibrary === 'next-intl') {
|
|
90
|
+
for (let lng in translations) {
|
|
91
|
+
fs.mkdirSync(path, { recursive: true });
|
|
57
92
|
|
|
58
|
-
for (let namespace in translations[lng]) {
|
|
59
93
|
fs.writeFileSync(
|
|
60
|
-
`${
|
|
61
|
-
JSON.stringify(translations[lng]
|
|
94
|
+
`${path}/${lng}.json`,
|
|
95
|
+
JSON.stringify(translations[lng])
|
|
62
96
|
);
|
|
63
97
|
}
|
|
98
|
+
} else {
|
|
99
|
+
for (let lng in translations) {
|
|
100
|
+
const lngFilePath = `${path}/${lng}`;
|
|
101
|
+
fs.mkdirSync(lngFilePath, { recursive: true });
|
|
102
|
+
|
|
103
|
+
for (let namespace in translations[lng]) {
|
|
104
|
+
fs.writeFileSync(
|
|
105
|
+
`${lngFilePath}/${namespace}.json`,
|
|
106
|
+
JSON.stringify(translations[lng][namespace])
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
64
110
|
}
|
|
65
111
|
|
|
66
112
|
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;
|