@gjsify/vite-plugin-gettext 0.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 +154 -0
- package/dist/gettext.d.ts +10 -0
- package/dist/gettext.js +73 -0
- package/dist/gettext.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/msgfmt.d.ts +9 -0
- package/dist/msgfmt.js +147 -0
- package/dist/msgfmt.js.map +1 -0
- package/dist/po2json.d.ts +9 -0
- package/dist/po2json.js +190 -0
- package/dist/po2json.js.map +1 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +37 -0
- package/dist/utils.js +94 -0
- package/dist/utils.js.map +1 -0
- package/dist/xgettext.d.ts +9 -0
- package/dist/xgettext.js +261 -0
- package/dist/xgettext.js.map +1 -0
- package/package.json +29 -0
- package/src/gettext.ts +104 -0
- package/src/index.ts +11 -0
- package/src/msgfmt.ts +209 -0
- package/src/po2json.ts +281 -0
- package/src/types.ts +120 -0
- package/src/utils.ts +119 -0
- package/src/xgettext.ts +337 -0
- package/tsconfig.json +22 -0
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# vite-plugin-gettext
|
|
2
|
+
|
|
3
|
+
A Vite plugin for managing GNU Gettext translations in your JavaScript/TypeScript applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Extracts translatable strings from source files using xgettext
|
|
8
|
+
- Automatically compiles PO translation files to binary MO format
|
|
9
|
+
- Compiles PO files to various formats (MO, XML, JSON, desktop entries, etc.)
|
|
10
|
+
- Supports metainfo files with ITS rules
|
|
11
|
+
- Watches for changes and recompiles during development
|
|
12
|
+
- Follows GNU Gettext standard directory structure
|
|
13
|
+
- Supports multiple languages
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @gjsify/vite-plugin-gettext --save-dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
or if you use Yarn:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
yarn add @gjsify/vite-plugin-gettext -D
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Add both plugins to your Vite configuration:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
// vite.config.js / vite.config.ts
|
|
33
|
+
import { defineConfig } from "vite";
|
|
34
|
+
import {
|
|
35
|
+
xgettextPlugin,
|
|
36
|
+
gettextPlugin,
|
|
37
|
+
msgfmtPlugin,
|
|
38
|
+
} from "@gjsify/vite-plugin-gettext";
|
|
39
|
+
export default defineConfig({
|
|
40
|
+
plugins: [
|
|
41
|
+
// Extract strings to POT file
|
|
42
|
+
xgettextPlugin({
|
|
43
|
+
sources: ["src/**/*.{ts,js}"],
|
|
44
|
+
output: "po/messages.pot",
|
|
45
|
+
domain: "myapp",
|
|
46
|
+
keywords: ["_", "gettext", "ngettext"],
|
|
47
|
+
verbose: true,
|
|
48
|
+
}),
|
|
49
|
+
// Compile PO files to MO format (standard approach)
|
|
50
|
+
gettextPlugin({
|
|
51
|
+
poDirectory: "po",
|
|
52
|
+
moDirectory: "public",
|
|
53
|
+
verbose: true,
|
|
54
|
+
}),
|
|
55
|
+
// Optionally use msgfmtPlugin for advanced use cases
|
|
56
|
+
msgfmtPlugin({
|
|
57
|
+
poDirectory: "po",
|
|
58
|
+
outputDirectory: "public",
|
|
59
|
+
domain: "myapp",
|
|
60
|
+
format: "xml", // Output format, e.g. 'xml' for metainfo
|
|
61
|
+
metainfo: true, // Enable metainfo support with ITS rules
|
|
62
|
+
verbose: true,
|
|
63
|
+
}),
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Requirements
|
|
69
|
+
|
|
70
|
+
- Vite 2.x or higher
|
|
71
|
+
- Node.js 12.x or higher
|
|
72
|
+
- GNU Gettext tools must be installed:
|
|
73
|
+
- Ubuntu/Debian: `sudo apt-get install gettext`
|
|
74
|
+
- Fedora: `sudo dnf install gettext`
|
|
75
|
+
- Arch: `sudo pacman -S gettext`
|
|
76
|
+
- macOS: `brew install gettext`
|
|
77
|
+
|
|
78
|
+
## How it Works
|
|
79
|
+
|
|
80
|
+
1. The `xgettextPlugin` extracts translatable strings from your source files into a POT template file
|
|
81
|
+
2. Translators create PO files for each language from the POT template
|
|
82
|
+
3. The `gettextPlugin` automatically compiles PO files to binary MO format
|
|
83
|
+
4. Alternatively, `msgfmtPlugin` can be used to compile to various formats with additional options
|
|
84
|
+
5. The MO files are placed in the standard gettext directory structure:
|
|
85
|
+
`{moDirectory}/locale/{lang}/LC_MESSAGES/messages.mo`
|
|
86
|
+
|
|
87
|
+
## Plugin Options
|
|
88
|
+
|
|
89
|
+
### xgettextPlugin Options
|
|
90
|
+
|
|
91
|
+
- `sources`: Array of glob patterns for source files to extract strings from
|
|
92
|
+
- `output`: Output path for the POT template file
|
|
93
|
+
- `domain`: The gettext domain name (defaults to 'messages')
|
|
94
|
+
- `keywords`: Keywords to look for when extracting strings (defaults to ['_', 'gettext', 'ngettext'])
|
|
95
|
+
- `xgettextOptions`: Additional options to pass to xgettext command
|
|
96
|
+
- `verbose`: Enable verbose logging
|
|
97
|
+
|
|
98
|
+
### gettextPlugin Options
|
|
99
|
+
|
|
100
|
+
- `poDirectory`: Directory containing PO translation files
|
|
101
|
+
- `moDirectory`: Output directory for compiled MO files
|
|
102
|
+
- `verbose`: Enable verbose logging
|
|
103
|
+
|
|
104
|
+
### msgfmtPlugin Options
|
|
105
|
+
|
|
106
|
+
- `poDirectory`: Directory containing PO translation files
|
|
107
|
+
- `outputDirectory`: Output directory for compiled files
|
|
108
|
+
- `domain`: The gettext domain name (defaults to 'messages')
|
|
109
|
+
- `format`: Output format, one of: 'mo', 'java', 'java2', 'csharp', 'csharp-resources', 'tcl', 'qt', 'desktop', 'xml', 'json' (defaults to 'mo')
|
|
110
|
+
- `verbose`: Enable verbose logging
|
|
111
|
+
- `msgfmtOptions`: Additional options to pass to msgfmt command
|
|
112
|
+
- `useLocaleStructure`: Whether to use the standard locale structure (defaults to true for 'mo' format)
|
|
113
|
+
|
|
114
|
+
## Examples
|
|
115
|
+
|
|
116
|
+
### Compiling PO files for metainfo XML files
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
msgfmtPlugin({
|
|
120
|
+
poDirectory: "po",
|
|
121
|
+
outputDirectory: "public/metainfo",
|
|
122
|
+
domain: "myapp",
|
|
123
|
+
format: "xml",
|
|
124
|
+
metainfo: true,
|
|
125
|
+
useLocaleStructure: false, // Output will be public/metainfo/LANG/myapp.xml
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Generating JSON translations for web applications
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
msgfmtPlugin({
|
|
133
|
+
poDirectory: "po",
|
|
134
|
+
outputDirectory: "public/i18n",
|
|
135
|
+
domain: "myapp",
|
|
136
|
+
format: "json",
|
|
137
|
+
useLocaleStructure: false, // Output will be public/i18n/LANG/myapp.json
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
The plugin is structured as follows:
|
|
144
|
+
|
|
145
|
+
- `src/gettext.ts` - Core plugin for compiling PO to MO files
|
|
146
|
+
- `src/msgfmt.ts` - Extended plugin for compiling PO to various formats
|
|
147
|
+
- `src/xgettext.ts` - Plugin for extracting strings from source code
|
|
148
|
+
- `src/utils.ts` - Shared utility functions
|
|
149
|
+
- `src/types.ts` - TypeScript type definitions
|
|
150
|
+
- `src/index.ts` - Main entry point that exports all plugins
|
|
151
|
+
|
|
152
|
+
## Contributing
|
|
153
|
+
|
|
154
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Plugin } from "vite";
|
|
2
|
+
import type { GettextPluginOptions } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a Vite plugin that compiles PO translation files to binary MO format
|
|
5
|
+
* The MO files are placed in the standard gettext directory structure:
|
|
6
|
+
* {moDirectory}/locale/{lang}/LC_MESSAGES/messages.mo
|
|
7
|
+
* @param options Configuration options for the plugin
|
|
8
|
+
* @returns A Vite plugin that handles PO compilation
|
|
9
|
+
*/
|
|
10
|
+
export declare function gettextPlugin(options: GettextPluginOptions): Plugin;
|
package/dist/gettext.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {} from "vite";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { checkDependencies, findAvailableLanguages, generateLinguasFile, ensureDirectory, } from "./utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Vite plugin that compiles PO translation files to binary MO format
|
|
7
|
+
* The MO files are placed in the standard gettext directory structure:
|
|
8
|
+
* {moDirectory}/locale/{lang}/LC_MESSAGES/messages.mo
|
|
9
|
+
* @param options Configuration options for the plugin
|
|
10
|
+
* @returns A Vite plugin that handles PO compilation
|
|
11
|
+
*/
|
|
12
|
+
export function gettextPlugin(options) {
|
|
13
|
+
const { poDirectory, moDirectory, filename = "messages.mo", verbose = false, } = options;
|
|
14
|
+
const pluginName = "vite-plugin-gettext";
|
|
15
|
+
async function compileMoFiles() {
|
|
16
|
+
try {
|
|
17
|
+
// Check if PO directory exists
|
|
18
|
+
try {
|
|
19
|
+
await ensureDirectory(poDirectory);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
if (verbose) {
|
|
23
|
+
console.log(`[${pluginName}] PO directory ${poDirectory} does not exist yet, skipping compilation`);
|
|
24
|
+
}
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Find available languages
|
|
28
|
+
const languages = await findAvailableLanguages(poDirectory, pluginName, verbose);
|
|
29
|
+
if (languages.length === 0) {
|
|
30
|
+
if (verbose) {
|
|
31
|
+
console.log(`[${pluginName}] No translation files found`);
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Generate LINGUAS file
|
|
36
|
+
await generateLinguasFile(languages, poDirectory, verbose);
|
|
37
|
+
// Create MO directory
|
|
38
|
+
await ensureDirectory(path.join(moDirectory, "locale"));
|
|
39
|
+
for (const lang of languages) {
|
|
40
|
+
const poFile = path.join(poDirectory, `${lang}.po`);
|
|
41
|
+
const moPath = path.join(moDirectory, "locale", lang, "LC_MESSAGES");
|
|
42
|
+
const moFile = path.join(moPath, filename);
|
|
43
|
+
await ensureDirectory(moPath);
|
|
44
|
+
if (verbose) {
|
|
45
|
+
console.log(`[${pluginName}] Compiling ${poFile} to ${moFile}`);
|
|
46
|
+
}
|
|
47
|
+
await execa("msgfmt", ["--output-file=" + moFile, poFile]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
throw new Error(`Failed to compile MO files: ${error}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
name: pluginName,
|
|
56
|
+
async buildStart() {
|
|
57
|
+
await checkDependencies("msgfmt", pluginName, verbose);
|
|
58
|
+
await compileMoFiles();
|
|
59
|
+
},
|
|
60
|
+
configureServer(server) {
|
|
61
|
+
server.watcher.add(poDirectory);
|
|
62
|
+
server.watcher.on("change", async (file) => {
|
|
63
|
+
if (file.endsWith(".po")) {
|
|
64
|
+
if (verbose) {
|
|
65
|
+
console.log(`[${pluginName}] PO file changed: ${file}, recompiling`);
|
|
66
|
+
}
|
|
67
|
+
await compileMoFiles();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=gettext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gettext.js","sourceRoot":"","sources":["../src/gettext.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { gettextPlugin } from "./gettext.js";
|
|
2
|
+
export { msgfmtPlugin } from "./msgfmt.js";
|
|
3
|
+
export { xgettextPlugin } from "./xgettext.js";
|
|
4
|
+
export { po2jsonPlugin } from "./po2json.js";
|
|
5
|
+
export type { GettextPluginOptions, MsgfmtPluginOptions, MsgfmtFormat, XGettextPluginOptions, } from "./types.js";
|
|
6
|
+
export * from "./utils.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAO7C,cAAc,YAAY,CAAC"}
|
package/dist/msgfmt.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Plugin } from "vite";
|
|
2
|
+
import type { MsgfmtPluginOptions } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a Vite plugin that compiles PO translation files to various formats
|
|
5
|
+
* Supports metainfo files with special processing
|
|
6
|
+
* @param options Configuration options for the plugin
|
|
7
|
+
* @returns A Vite plugin that handles PO compilation
|
|
8
|
+
*/
|
|
9
|
+
export declare function msgfmtPlugin(options: MsgfmtPluginOptions): Plugin;
|
package/dist/msgfmt.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import {} from "vite";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { checkDependencies, findAvailableLanguages, ensureDirectory, } from "./utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* Get output file extension based on the format
|
|
7
|
+
* @param format The output format
|
|
8
|
+
* @returns The file extension for the given format
|
|
9
|
+
*/
|
|
10
|
+
function getOutputExtension(format) {
|
|
11
|
+
switch (format) {
|
|
12
|
+
case "mo":
|
|
13
|
+
return ".mo";
|
|
14
|
+
case "java":
|
|
15
|
+
case "java2":
|
|
16
|
+
return ".class";
|
|
17
|
+
case "csharp":
|
|
18
|
+
return ".dll";
|
|
19
|
+
case "csharp-resources":
|
|
20
|
+
return ".resources.dll";
|
|
21
|
+
case "tcl":
|
|
22
|
+
return ".msg";
|
|
23
|
+
case "desktop":
|
|
24
|
+
return ".desktop";
|
|
25
|
+
case "xml":
|
|
26
|
+
return ".xml";
|
|
27
|
+
case "json":
|
|
28
|
+
return ".json";
|
|
29
|
+
case "qt":
|
|
30
|
+
return ".qm";
|
|
31
|
+
default:
|
|
32
|
+
return ".mo";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a Vite plugin that compiles PO translation files to various formats
|
|
37
|
+
* Supports metainfo files with special processing
|
|
38
|
+
* @param options Configuration options for the plugin
|
|
39
|
+
* @returns A Vite plugin that handles PO compilation
|
|
40
|
+
*/
|
|
41
|
+
export function msgfmtPlugin(options) {
|
|
42
|
+
const { poDirectory, outputDirectory, domain = "messages", format = "mo", templateFile, verbose = false, msgfmtOptions = [], useLocaleStructure = true, } = options;
|
|
43
|
+
const pluginName = "vite-plugin-msgfmt";
|
|
44
|
+
async function compilePoFiles() {
|
|
45
|
+
try {
|
|
46
|
+
// Check if PO directory exists
|
|
47
|
+
try {
|
|
48
|
+
await ensureDirectory(poDirectory);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
if (verbose) {
|
|
52
|
+
console.log(`[${pluginName}] PO directory ${poDirectory} does not exist yet, skipping compilation`);
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Create output directory
|
|
57
|
+
await ensureDirectory(outputDirectory);
|
|
58
|
+
// For XML format, we can use the bulk mode if a template is provided
|
|
59
|
+
if (format === "xml" && templateFile) {
|
|
60
|
+
// Use bulk mode for XML format
|
|
61
|
+
const outputFile = path.join(outputDirectory, options.filename || `${domain}${getOutputExtension(format)}`);
|
|
62
|
+
if (verbose) {
|
|
63
|
+
console.log(`[${pluginName}] Compiling all languages to ${outputFile} using bulk mode`);
|
|
64
|
+
}
|
|
65
|
+
// Base arguments for bulk mode
|
|
66
|
+
const args = [
|
|
67
|
+
"--output-file=" + outputFile,
|
|
68
|
+
"--xml",
|
|
69
|
+
"--template=" + templateFile,
|
|
70
|
+
"-d",
|
|
71
|
+
poDirectory,
|
|
72
|
+
];
|
|
73
|
+
// Add any additional options
|
|
74
|
+
args.push(...msgfmtOptions);
|
|
75
|
+
if (verbose) {
|
|
76
|
+
console.log(`[${pluginName}] Running msgfmt with: ${args.join(" ")}`);
|
|
77
|
+
}
|
|
78
|
+
await execa("msgfmt", args);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Find available languages for individual processing
|
|
82
|
+
const languages = await findAvailableLanguages(poDirectory, pluginName, verbose);
|
|
83
|
+
if (languages.length === 0) {
|
|
84
|
+
if (verbose) {
|
|
85
|
+
console.log(`[${pluginName}] No translation files found`);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Process each language individually for other formats
|
|
90
|
+
for (const lang of languages) {
|
|
91
|
+
const poFile = path.join(poDirectory, `${lang}.po`);
|
|
92
|
+
let outputPath;
|
|
93
|
+
let outputFile;
|
|
94
|
+
if (useLocaleStructure && format === "mo") {
|
|
95
|
+
// Use standard gettext locale structure
|
|
96
|
+
outputPath = path.join(outputDirectory, "locale", lang, "LC_MESSAGES");
|
|
97
|
+
outputFile = path.join(outputPath, options.filename || `${domain}${getOutputExtension(format)}`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Use simple language-based structure
|
|
101
|
+
outputPath = path.join(outputDirectory, lang);
|
|
102
|
+
outputFile = path.join(outputPath, options.filename || `${domain}${getOutputExtension(format)}`);
|
|
103
|
+
}
|
|
104
|
+
// Create the directory structure
|
|
105
|
+
await ensureDirectory(outputPath);
|
|
106
|
+
if (verbose) {
|
|
107
|
+
console.log(`[${pluginName}] Compiling ${poFile} to ${outputFile}`);
|
|
108
|
+
}
|
|
109
|
+
// Base arguments
|
|
110
|
+
const args = ["--output-file=" + outputFile];
|
|
111
|
+
// Add format-specific arguments
|
|
112
|
+
args.push(`--${format}`);
|
|
113
|
+
// Add any additional options
|
|
114
|
+
args.push(...msgfmtOptions);
|
|
115
|
+
// Add the input PO file
|
|
116
|
+
args.push(poFile);
|
|
117
|
+
if (verbose) {
|
|
118
|
+
console.log(`[${pluginName}] Running msgfmt with: ${args.join(" ")}`);
|
|
119
|
+
}
|
|
120
|
+
await execa("msgfmt", args);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
throw new Error(`Failed to compile files: ${error}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
name: pluginName,
|
|
130
|
+
async buildStart() {
|
|
131
|
+
await checkDependencies("msgfmt", pluginName, verbose);
|
|
132
|
+
await compilePoFiles();
|
|
133
|
+
},
|
|
134
|
+
configureServer(server) {
|
|
135
|
+
server.watcher.add(poDirectory);
|
|
136
|
+
server.watcher.on("change", async (file) => {
|
|
137
|
+
if (file.endsWith(".po")) {
|
|
138
|
+
if (verbose) {
|
|
139
|
+
console.log(`[${pluginName}] PO file changed: ${file}, recompiling`);
|
|
140
|
+
}
|
|
141
|
+
await compilePoFiles();
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=msgfmt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msgfmt.js","sourceRoot":"","sources":["../src/msgfmt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Plugin } from "vite";
|
|
2
|
+
import type { GettextPo2JsonPluginOptions } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a Vite plugin that converts PO translation files to JSON format
|
|
5
|
+
* The JSON files are placed in the specified output directory
|
|
6
|
+
* @param options Configuration options for the plugin
|
|
7
|
+
* @returns A Vite plugin that handles PO to JSON conversion
|
|
8
|
+
*/
|
|
9
|
+
export declare function po2jsonPlugin(options: GettextPo2JsonPluginOptions): Plugin;
|
package/dist/po2json.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import {} from "vite";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import * as gettextParser from "gettext-parser";
|
|
5
|
+
import { checkDependencies, findAvailableLanguages, ensureDirectory, } from "./utils.js";
|
|
6
|
+
/**
|
|
7
|
+
* Simplifies the gettext-parser output to a clean key-value object
|
|
8
|
+
* where the key is the original text and the value is the translation
|
|
9
|
+
* @param translations The parsed PO file from gettext-parser
|
|
10
|
+
* @returns A simplified object with just the translations
|
|
11
|
+
*/
|
|
12
|
+
function simplifyTranslations(translations) {
|
|
13
|
+
const result = {};
|
|
14
|
+
// Go through all translation contexts
|
|
15
|
+
Object.keys(translations.translations).forEach((context) => {
|
|
16
|
+
const contextTranslations = translations.translations[context];
|
|
17
|
+
// Skip the header (empty msgid)
|
|
18
|
+
Object.keys(contextTranslations).forEach((key) => {
|
|
19
|
+
if (key === "")
|
|
20
|
+
return;
|
|
21
|
+
const translation = contextTranslations[key];
|
|
22
|
+
// Get the original text (msgid)
|
|
23
|
+
const original = translation.msgid;
|
|
24
|
+
// Get the translated text (first item in msgstr array)
|
|
25
|
+
const translated = translation.msgstr[0];
|
|
26
|
+
// Only add the translation if it exists and is not empty
|
|
27
|
+
if (translated && translated.trim() !== "") {
|
|
28
|
+
result[original] = translated;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a dictionary of all original strings from all translations
|
|
36
|
+
* For the default language, we need to gather all possible keys
|
|
37
|
+
* @param jsonDirectory Directory with JSON files
|
|
38
|
+
* @param allTranslations Collection of all translations
|
|
39
|
+
* @param defaultLanguage The default language code
|
|
40
|
+
* @param verbose Whether to log verbose messages
|
|
41
|
+
* @param pluginName The name of the plugin
|
|
42
|
+
* @param additionalTranslations Additional translations to include
|
|
43
|
+
* @returns Object with original strings as both keys and values
|
|
44
|
+
*/
|
|
45
|
+
async function createDefaultLanguageJson(jsonDirectory, allTranslations, defaultLanguage, verbose, pluginName, additionalTranslations = {}) {
|
|
46
|
+
// Create a set of all original strings from all translations
|
|
47
|
+
const allOriginalStrings = new Set();
|
|
48
|
+
// Collect all original strings from all translations
|
|
49
|
+
Object.values(allTranslations).forEach((translations) => {
|
|
50
|
+
Object.keys(translations).forEach((key) => {
|
|
51
|
+
allOriginalStrings.add(key);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
// Create the default language JSON with keys matching values
|
|
55
|
+
const defaultLanguageJson = {};
|
|
56
|
+
allOriginalStrings.forEach((str) => {
|
|
57
|
+
defaultLanguageJson[str] = str;
|
|
58
|
+
});
|
|
59
|
+
// Process additional translations
|
|
60
|
+
const finalTranslations = { ...defaultLanguageJson };
|
|
61
|
+
// For each additional translation, try to find a translation or use the original
|
|
62
|
+
Object.entries(additionalTranslations).forEach(([key, originalText]) => {
|
|
63
|
+
// If there's a translation for the original text, use it
|
|
64
|
+
if (defaultLanguageJson[originalText]) {
|
|
65
|
+
finalTranslations[key] = defaultLanguageJson[originalText];
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Otherwise use the original text
|
|
69
|
+
finalTranslations[key] = originalText;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
// Write the default language file with .default.json extension
|
|
73
|
+
const defaultLangDefaultFile = path.join(jsonDirectory, `${defaultLanguage}.default.json`);
|
|
74
|
+
if (verbose) {
|
|
75
|
+
console.log(`[${pluginName}] Creating default language file: ${defaultLangDefaultFile}`);
|
|
76
|
+
}
|
|
77
|
+
await fs.writeFile(defaultLangDefaultFile, JSON.stringify(finalTranslations, null, 2));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Creates a Vite plugin that converts PO translation files to JSON format
|
|
81
|
+
* The JSON files are placed in the specified output directory
|
|
82
|
+
* @param options Configuration options for the plugin
|
|
83
|
+
* @returns A Vite plugin that handles PO to JSON conversion
|
|
84
|
+
*/
|
|
85
|
+
export function po2jsonPlugin(options) {
|
|
86
|
+
const { poDirectory, jsonDirectory, defaultLanguage = "en", verbose = false, additionalTranslations = {}, } = options;
|
|
87
|
+
const pluginName = "vite-plugin-gettext-po2json";
|
|
88
|
+
async function convertPoToJson() {
|
|
89
|
+
try {
|
|
90
|
+
// Check if PO directory exists
|
|
91
|
+
try {
|
|
92
|
+
await ensureDirectory(poDirectory);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
if (verbose) {
|
|
96
|
+
console.log(`[${pluginName}] PO directory ${poDirectory} does not exist yet, skipping conversion`);
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Find available languages
|
|
101
|
+
const languages = await findAvailableLanguages(poDirectory, pluginName, verbose);
|
|
102
|
+
if (languages.length === 0) {
|
|
103
|
+
if (verbose) {
|
|
104
|
+
console.log(`[${pluginName}] No translation files found`);
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Create JSON directory
|
|
109
|
+
await ensureDirectory(jsonDirectory);
|
|
110
|
+
// Collection of all translations to create the default language file
|
|
111
|
+
const allTranslations = {};
|
|
112
|
+
// Skip the default language if it exists in the list
|
|
113
|
+
const nonDefaultLanguages = languages.filter((lang) => lang !== defaultLanguage);
|
|
114
|
+
// Handle default language if it exists in the list
|
|
115
|
+
if (languages.includes(defaultLanguage)) {
|
|
116
|
+
const poFile = path.join(poDirectory, `${defaultLanguage}.po`);
|
|
117
|
+
const jsonFile = path.join(jsonDirectory, `${defaultLanguage}.json`);
|
|
118
|
+
if (verbose) {
|
|
119
|
+
console.log(`[${pluginName}] Converting default language ${poFile} to ${jsonFile}`);
|
|
120
|
+
}
|
|
121
|
+
// Read and parse PO file
|
|
122
|
+
const poContent = await fs.readFile(poFile);
|
|
123
|
+
const translations = gettextParser.po.parse(poContent);
|
|
124
|
+
// Convert the translations to a simple JSON object
|
|
125
|
+
const simplifiedTranslations = simplifyTranslations(translations);
|
|
126
|
+
// Process additional translations for default language
|
|
127
|
+
const finalTranslations = { ...simplifiedTranslations };
|
|
128
|
+
// For each additional translation, add it to the default language file
|
|
129
|
+
Object.entries(additionalTranslations).forEach(([key, originalText]) => {
|
|
130
|
+
finalTranslations[key] = originalText;
|
|
131
|
+
});
|
|
132
|
+
// Write JSON file for default language
|
|
133
|
+
await fs.writeFile(jsonFile, JSON.stringify(finalTranslations, null, 2));
|
|
134
|
+
}
|
|
135
|
+
// Add additional translations for all languages
|
|
136
|
+
for (const lang of nonDefaultLanguages) {
|
|
137
|
+
const poFile = path.join(poDirectory, `${lang}.po`);
|
|
138
|
+
const jsonFile = path.join(jsonDirectory, `${lang}.json`);
|
|
139
|
+
if (verbose) {
|
|
140
|
+
console.log(`[${pluginName}] Converting ${poFile} to ${jsonFile}`);
|
|
141
|
+
}
|
|
142
|
+
// Read and parse PO file
|
|
143
|
+
const poContent = await fs.readFile(poFile);
|
|
144
|
+
const translations = gettextParser.po.parse(poContent);
|
|
145
|
+
// Convert the translations to a simple JSON object
|
|
146
|
+
const simplifiedTranslations = simplifyTranslations(translations);
|
|
147
|
+
// Store translations for creating the default language file
|
|
148
|
+
allTranslations[lang] = simplifiedTranslations;
|
|
149
|
+
// Process additional translations
|
|
150
|
+
const finalTranslations = { ...simplifiedTranslations };
|
|
151
|
+
// For each additional translation, try to find a translation or use the original
|
|
152
|
+
Object.entries(additionalTranslations).forEach(([key, originalText]) => {
|
|
153
|
+
// If there's a translation for the original text, use it
|
|
154
|
+
if (simplifiedTranslations[originalText]) {
|
|
155
|
+
finalTranslations[key] = simplifiedTranslations[originalText];
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// Otherwise use the original text
|
|
159
|
+
finalTranslations[key] = originalText;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
// Write JSON file
|
|
163
|
+
await fs.writeFile(jsonFile, JSON.stringify(finalTranslations, null, 2));
|
|
164
|
+
}
|
|
165
|
+
// Create the default language file (with all original strings as both keys and values)
|
|
166
|
+
await createDefaultLanguageJson(jsonDirectory, allTranslations, defaultLanguage, verbose, pluginName, additionalTranslations);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
throw new Error(`Failed to convert PO files to JSON: ${error}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
name: pluginName,
|
|
174
|
+
async buildStart() {
|
|
175
|
+
await convertPoToJson();
|
|
176
|
+
},
|
|
177
|
+
configureServer(server) {
|
|
178
|
+
server.watcher.add(poDirectory);
|
|
179
|
+
server.watcher.on("change", async (file) => {
|
|
180
|
+
if (file.endsWith(".po")) {
|
|
181
|
+
if (verbose) {
|
|
182
|
+
console.log(`[${pluginName}] PO file changed: ${file}, reconverting`);
|
|
183
|
+
}
|
|
184
|
+
await convertPoToJson();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=po2json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"po2json.js","sourceRoot":"","sources":["../src/po2json.ts"],"names":[],"mappings":"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"}
|