@unisphere/nx 4.14.4 → 4.15.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/dist/generators/add-package/templates/new-package/src/languages/README.md +52 -0
- package/dist/generators/add-package/templates/new-package/src/languages/en-US.json +1 -0
- package/dist/generators/add-package/templates/new-package/src/languages/files/.gitkeep +0 -0
- package/dist/generators/add-package/templates/new-package/src/languages/supported-languges.ts +1 -0
- package/dist/generators/add-package/templates/new-package/src/lib/use-translation.tsx.template +9 -0
- package/dist/generators/add-runtime/templates/new-runtime/src/languages/README.md +32 -0
- package/dist/generators/add-runtime/templates/new-runtime/src/languages/en-US.json +1 -0
- package/dist/generators/add-runtime/templates/new-runtime/src/languages/files/.gitkeep +0 -0
- package/dist/generators/add-runtime/templates/new-runtime/src/languages/supported-languges.ts +1 -0
- package/dist/generators/add-runtime/templates/new-runtime/src/lib/runtime.tsx.template +1 -0
- package/dist/generators/add-runtime/templates/new-runtime/src/lib/use-translation.tsx.template +9 -0
- package/dist/generators/add-visual/templates/new-visual/render-method.template +1 -0
- package/dist/migrations/4-15-0/add-languages-support.d.ts +16 -0
- package/dist/migrations/4-15-0/add-languages-support.d.ts.map +1 -0
- package/dist/migrations/4-15-0/add-languages-support.js +629 -0
- package/migrations.json +23 -0
- package/package.json +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Languages
|
|
2
|
+
|
|
3
|
+
This folder contains the internationalization (i18n) setup for this package.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
languages/
|
|
9
|
+
├── en-US.json # Default English translations (source of truth)
|
|
10
|
+
├── supported-languges.ts # List of supported language codes
|
|
11
|
+
├── files/ # Translated language files (e.g., de-DE.json, fr-FR.json)
|
|
12
|
+
│ └── .gitkeep
|
|
13
|
+
├── _db/ # Translation database for change tracking (git-ignored)
|
|
14
|
+
│ └── .gitignore
|
|
15
|
+
└── README.md # This file
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## How It Works
|
|
19
|
+
|
|
20
|
+
- **`en-US.json`** — The master translation file. All keys are defined here in English.
|
|
21
|
+
- **`supported-languges.ts`** — Exports the list of supported language codes. Add new languages here when translations are available.
|
|
22
|
+
- **`files/`** — Contains translated JSON files for each supported language (excluding en-US). These are generated via the Unisphere CLI export/import workflow.
|
|
23
|
+
- **`_db/`** — Used internally by the CLI to track translation changes between exports. Do not commit.
|
|
24
|
+
|
|
25
|
+
## Adding Translations
|
|
26
|
+
|
|
27
|
+
1. Add your translation keys to `en-US.json`
|
|
28
|
+
2. Run `npx unisphere languages export` to generate CSV files for translators
|
|
29
|
+
3. After receiving translations, run `npx unisphere languages import` to update the `files/` directory
|
|
30
|
+
4. Add the new language code to `supported-languges.ts`
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
Components in this package use translations via the `useTranslation` hook:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { useTranslation } from './use-translation';
|
|
38
|
+
|
|
39
|
+
const MyComponent = () => {
|
|
40
|
+
const { t } = useTranslation();
|
|
41
|
+
return <span>{t('myKey')}</span>;
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## CLI Commands
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx unisphere languages export # Export translations to CSV for translation services
|
|
49
|
+
npx unisphere languages import # Import translated CSV files back to JSON
|
|
50
|
+
npx unisphere languages serve # Serve language files during local development
|
|
51
|
+
npx unisphere languages bundle # Bundle language files for distribution
|
|
52
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const supportedLanguages: string[] = ['en-US'];
|
package/dist/generators/add-package/templates/new-package/src/lib/use-translation.tsx.template
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import en from '../languages/en-US.json';
|
|
2
|
+
import { createUseTranslation } from '@unisphere/ui-i18n-react';
|
|
3
|
+
import { supportedLanguages } from '../languages/supported-languges';
|
|
4
|
+
|
|
5
|
+
export const useTranslation = createUseTranslation({
|
|
6
|
+
packageName: '<%= packageJsonName %>',
|
|
7
|
+
defaultTranslations: en as any,
|
|
8
|
+
supportedLanguages,
|
|
9
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Languages
|
|
2
|
+
|
|
3
|
+
This folder contains the internationalization (i18n) setup for this runtime.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
languages/
|
|
9
|
+
├── en-US.json # Default English translations (source of truth)
|
|
10
|
+
├── supported-languges.ts # List of supported language codes
|
|
11
|
+
├── files/ # Translated language files (e.g., de-DE.json, fr-FR.json)
|
|
12
|
+
│ └── .gitkeep
|
|
13
|
+
├── _db/ # Translation database for change tracking (git-ignored)
|
|
14
|
+
│ └── .gitignore
|
|
15
|
+
└── README.md # This file
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## How It Works
|
|
19
|
+
|
|
20
|
+
- **`en-US.json`** — The master translation file. All keys are defined here in English.
|
|
21
|
+
- **`supported-languges.ts`** — Exports the list of supported language codes. Add new languages here when translations are available.
|
|
22
|
+
- **`files/`** — Contains translated JSON files for each supported language (excluding en-US). These are generated via the Unisphere CLI export/import workflow.
|
|
23
|
+
- **`_db/`** — Used internally by the CLI to track translation changes between exports. Do not commit.
|
|
24
|
+
|
|
25
|
+
## CLI Commands
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx unisphere languages export # Export translations to CSV for translation services
|
|
29
|
+
npx unisphere languages import # Import translated CSV files back to JSON
|
|
30
|
+
npx unisphere languages serve # Serve language files during local development
|
|
31
|
+
npx unisphere languages bundle # Bundle language files for distribution
|
|
32
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const supportedLanguages: string[] = ['en-US'];
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
widgetName,
|
|
13
13
|
} from '<%= typesAlias %>';
|
|
14
14
|
import { HtmlDomRuntimeVisual, KalturaAnalyticsServiceType } from '@unisphere/runtime';
|
|
15
|
+
import { UnisphereI18NRuntimeProxy } from '@unisphere/ui-i18n-react';
|
|
15
16
|
|
|
16
17
|
export class Runtime
|
|
17
18
|
extends UnisphereRuntimeBase<<%= runtimeName__pascalCase %>RuntimeSettings, Root>
|
package/dist/generators/add-runtime/templates/new-runtime/src/lib/use-translation.tsx.template
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import en from '../languages/en-US.json';
|
|
2
|
+
import { createUseTranslation } from '@unisphere/ui-i18n-react';
|
|
3
|
+
import { supportedLanguages } from '../languages/supported-languges';
|
|
4
|
+
|
|
5
|
+
export const useTranslation = createUseTranslation({
|
|
6
|
+
packageName: 'self',
|
|
7
|
+
defaultTranslations: en as any,
|
|
8
|
+
supportedLanguages,
|
|
9
|
+
});
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
visual.htmlContainer?.render(
|
|
12
12
|
<ScopedUnisphereWorkspaceProvider unisphereWorkspace={this._workspace} runtimeLogger={this._logger}>
|
|
13
|
+
<UnisphereI18NRuntimeProxy runtimeUri={this._options.runtimeDeployedPath} />
|
|
13
14
|
<ThemeProvider
|
|
14
15
|
cssPrefix={'<%= widgetName__lowerDashCase %>-<%= runtimeName__lowerDashCase %>-<%= visualName__lowerDashCase %>'}
|
|
15
16
|
mode={typeof this._theme === 'string' ? this._theme : this._theme.mode}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: Add Unisphere Languages Support
|
|
3
|
+
*
|
|
4
|
+
* Migrates packages from raw i18next/react-i18next to the Unisphere
|
|
5
|
+
* @unisphere/ui-i18n-react framework with createUseTranslation pattern.
|
|
6
|
+
* Adds UnisphereI18NRuntimeProxy to all runtimes.
|
|
7
|
+
*
|
|
8
|
+
* Steps:
|
|
9
|
+
* 1. For packages with existing en-US.json: move translations, create
|
|
10
|
+
* use-translation.tsx, update imports, remove LanguagesProvider
|
|
11
|
+
* 2. For all runtimes: add UnisphereI18NRuntimeProxy, remove LanguagesProvider usage
|
|
12
|
+
* 3. Update root package.json dependencies
|
|
13
|
+
*/
|
|
14
|
+
import { Tree } from '@nx/devkit';
|
|
15
|
+
export default function update(tree: Tree): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=add-languages-support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-languages-support.d.ts","sourceRoot":"","sources":["../../../src/migrations/4-15-0/add-languages-support.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,IAAI,EAML,MAAM,YAAY,CAAC;AAiBpB,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB9D"}
|
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Migration: Add Unisphere Languages Support
|
|
4
|
+
*
|
|
5
|
+
* Migrates packages from raw i18next/react-i18next to the Unisphere
|
|
6
|
+
* @unisphere/ui-i18n-react framework with createUseTranslation pattern.
|
|
7
|
+
* Adds UnisphereI18NRuntimeProxy to all runtimes.
|
|
8
|
+
*
|
|
9
|
+
* Steps:
|
|
10
|
+
* 1. For packages with existing en-US.json: move translations, create
|
|
11
|
+
* use-translation.tsx, update imports, remove LanguagesProvider
|
|
12
|
+
* 2. For all runtimes: add UnisphereI18NRuntimeProxy, remove LanguagesProvider usage
|
|
13
|
+
* 3. Update root package.json dependencies
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.default = update;
|
|
17
|
+
const tslib_1 = require("tslib");
|
|
18
|
+
const devkit_1 = require("@nx/devkit");
|
|
19
|
+
const path = tslib_1.__importStar(require("path"));
|
|
20
|
+
async function update(tree) {
|
|
21
|
+
devkit_1.logger.info('🔄 Adding Unisphere languages support...');
|
|
22
|
+
if (!tree.exists('.unisphere')) {
|
|
23
|
+
devkit_1.logger.info('ℹ️ No .unisphere config found, skipping');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const config = (0, devkit_1.readJson)(tree, '.unisphere');
|
|
27
|
+
const packages = config.elements?.packages || {};
|
|
28
|
+
const runtimes = config.elements?.runtimes || {};
|
|
29
|
+
// Step 1: Migrate packages with existing translations
|
|
30
|
+
const migratedPackages = migratePackages(tree, packages);
|
|
31
|
+
// Step 2: Migrate all runtimes
|
|
32
|
+
migrateRuntimes(tree, runtimes, migratedPackages);
|
|
33
|
+
// Step 3: Update root package.json
|
|
34
|
+
updateRootPackageJson(tree);
|
|
35
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
36
|
+
devkit_1.logger.info('✅ Unisphere languages support migration complete');
|
|
37
|
+
}
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// Step 1: Package Migrations
|
|
40
|
+
// =============================================================================
|
|
41
|
+
function migratePackages(tree, packages) {
|
|
42
|
+
const migratedPackages = [];
|
|
43
|
+
for (const [name, config] of Object.entries(packages)) {
|
|
44
|
+
const { sourceRoot } = config;
|
|
45
|
+
if (!tree.exists(sourceRoot)) {
|
|
46
|
+
devkit_1.logger.warn(` ⚠️ Package "${name}" source root not found: ${sourceRoot}`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
// Find existing en-US.json under this package
|
|
50
|
+
const translationFile = findTranslationFile(tree, sourceRoot);
|
|
51
|
+
// Read package name from package.json
|
|
52
|
+
const packageJsonPath = `${sourceRoot}/package.json`;
|
|
53
|
+
let packageName = `@local/${name}`;
|
|
54
|
+
if (tree.exists(packageJsonPath)) {
|
|
55
|
+
const pkgJson = (0, devkit_1.readJson)(tree, packageJsonPath);
|
|
56
|
+
packageName = pkgJson.name || packageName;
|
|
57
|
+
}
|
|
58
|
+
devkit_1.logger.info(` 📦 Migrating package "${name}" (${packageName})...`);
|
|
59
|
+
// 1a. Move translation file to src/languages/en-US.json or create empty one
|
|
60
|
+
const targetTranslationPath = `${sourceRoot}/src/languages/en-US.json`;
|
|
61
|
+
if (translationFile) {
|
|
62
|
+
moveTranslationFile(tree, translationFile, targetTranslationPath);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Create empty en-US.json if none existed
|
|
66
|
+
if (!tree.exists(targetTranslationPath)) {
|
|
67
|
+
tree.write(targetTranslationPath, '{}');
|
|
68
|
+
devkit_1.logger.info(` ✅ Created empty ${targetTranslationPath}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// 1b. Create _db/.gitignore
|
|
72
|
+
const dbGitignorePath = `${sourceRoot}/src/languages/_db/.gitignore`;
|
|
73
|
+
if (!tree.exists(dbGitignorePath)) {
|
|
74
|
+
tree.write(dbGitignorePath, '');
|
|
75
|
+
}
|
|
76
|
+
// 1c. Create files/.gitkeep
|
|
77
|
+
const filesGitkeepPath = `${sourceRoot}/src/languages/files/.gitkeep`;
|
|
78
|
+
if (!tree.exists(filesGitkeepPath)) {
|
|
79
|
+
tree.write(filesGitkeepPath, '');
|
|
80
|
+
}
|
|
81
|
+
// 1d. Create supported-languges.ts
|
|
82
|
+
const supportedLanguagesPath = `${sourceRoot}/src/languages/supported-languges.ts`;
|
|
83
|
+
createSupportedLanguagesFile(tree, supportedLanguagesPath);
|
|
84
|
+
// 1e. Create use-translation.tsx (if not already present)
|
|
85
|
+
const useTranslationPath = `${sourceRoot}/src/lib/use-translation.tsx`;
|
|
86
|
+
createUseTranslationFile(tree, useTranslationPath, packageName);
|
|
87
|
+
// 1f. Create README.md in languages folder
|
|
88
|
+
const readmePath = `${sourceRoot}/src/languages/README.md`;
|
|
89
|
+
createLanguagesReadme(tree, readmePath);
|
|
90
|
+
// 1g. Update useTranslation imports in package files
|
|
91
|
+
updateUseTranslationImports(tree, sourceRoot, useTranslationPath);
|
|
92
|
+
// 1h. Remove LanguagesProvider usage from package files
|
|
93
|
+
removeLanguagesProviderUsage(tree, sourceRoot);
|
|
94
|
+
// 1i. Delete languages-provider.tsx
|
|
95
|
+
deleteLanguagesProvider(tree, sourceRoot);
|
|
96
|
+
// 1j. Update barrel export
|
|
97
|
+
updateBarrelExport(tree, sourceRoot);
|
|
98
|
+
// 1k. Export useTranslation from barrel for runtime consumption
|
|
99
|
+
exportUseTranslationFromBarrel(tree, sourceRoot);
|
|
100
|
+
migratedPackages.push({
|
|
101
|
+
name,
|
|
102
|
+
sourceRoot,
|
|
103
|
+
packageName,
|
|
104
|
+
translationFilePath: targetTranslationPath,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (migratedPackages.length === 0) {
|
|
108
|
+
devkit_1.logger.info('ℹ️ No packages with translations found');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
devkit_1.logger.info(` ✅ Migrated ${migratedPackages.length} package(s) with translations`);
|
|
112
|
+
}
|
|
113
|
+
return migratedPackages;
|
|
114
|
+
}
|
|
115
|
+
function findTranslationFile(tree, sourceRoot) {
|
|
116
|
+
let found = null;
|
|
117
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, sourceRoot, (filePath) => {
|
|
118
|
+
if (found)
|
|
119
|
+
return;
|
|
120
|
+
if (filePath.endsWith('/en-US.json') && filePath.includes('/languages/')) {
|
|
121
|
+
found = filePath;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// Fallback: look for en-US.json anywhere under src
|
|
125
|
+
if (!found) {
|
|
126
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, sourceRoot, (filePath) => {
|
|
127
|
+
if (found)
|
|
128
|
+
return;
|
|
129
|
+
if (filePath.endsWith('/en-US.json')) {
|
|
130
|
+
found = filePath;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return found;
|
|
135
|
+
}
|
|
136
|
+
function moveTranslationFile(tree, from, to) {
|
|
137
|
+
if (from === to)
|
|
138
|
+
return;
|
|
139
|
+
if (tree.exists(to)) {
|
|
140
|
+
devkit_1.logger.info(` ℹ️ Translation file already at target: ${to}`);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const content = tree.read(from, 'utf-8');
|
|
144
|
+
if (content) {
|
|
145
|
+
tree.write(to, content);
|
|
146
|
+
tree.delete(from);
|
|
147
|
+
devkit_1.logger.info(` 📁 Moved ${from} → ${to}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function createSupportedLanguagesFile(tree, filePath) {
|
|
151
|
+
if (tree.exists(filePath)) {
|
|
152
|
+
devkit_1.logger.info(` ℹ️ supported-languges.ts already exists`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const content = `export const supportedLanguages: string[] = ['en-US'];\n`;
|
|
156
|
+
tree.write(filePath, content);
|
|
157
|
+
devkit_1.logger.info(` ✅ Created ${filePath}`);
|
|
158
|
+
}
|
|
159
|
+
function createUseTranslationFile(tree, filePath, packageName) {
|
|
160
|
+
if (tree.exists(filePath)) {
|
|
161
|
+
devkit_1.logger.info(` ℹ️ use-translation.tsx already exists`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const content = `import en from '../languages/en-US.json';
|
|
165
|
+
import { createUseTranslation } from '@unisphere/ui-i18n-react';
|
|
166
|
+
import { supportedLanguages } from '../languages/supported-languges';
|
|
167
|
+
|
|
168
|
+
export const useTranslation = createUseTranslation({
|
|
169
|
+
packageName: '${packageName}',
|
|
170
|
+
defaultTranslations: en as any,
|
|
171
|
+
supportedLanguages,
|
|
172
|
+
});
|
|
173
|
+
`;
|
|
174
|
+
tree.write(filePath, content);
|
|
175
|
+
devkit_1.logger.info(` ✅ Created ${filePath}`);
|
|
176
|
+
}
|
|
177
|
+
function createLanguagesReadme(tree, filePath) {
|
|
178
|
+
if (tree.exists(filePath)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const content = `# Languages
|
|
182
|
+
|
|
183
|
+
This folder contains the internationalization (i18n) setup for this package.
|
|
184
|
+
|
|
185
|
+
## Structure
|
|
186
|
+
|
|
187
|
+
\`\`\`
|
|
188
|
+
languages/
|
|
189
|
+
├── en-US.json # Default English translations (source of truth)
|
|
190
|
+
├── supported-languges.ts # List of supported language codes
|
|
191
|
+
├── files/ # Translated language files (e.g., de-DE.json, fr-FR.json)
|
|
192
|
+
│ └── .gitkeep
|
|
193
|
+
├── _db/ # Translation database for change tracking (git-ignored)
|
|
194
|
+
│ └── .gitignore
|
|
195
|
+
└── README.md # This file
|
|
196
|
+
\`\`\`
|
|
197
|
+
|
|
198
|
+
## How It Works
|
|
199
|
+
|
|
200
|
+
- **\`en-US.json\`** — The master translation file. All keys are defined here in English.
|
|
201
|
+
- **\`supported-languges.ts\`** — Exports the list of supported language codes. Add new languages here when translations are available.
|
|
202
|
+
- **\`files/\`** — Contains translated JSON files for each supported language (excluding en-US). These are generated via the Unisphere CLI export/import workflow.
|
|
203
|
+
- **\`_db/\`** — Used internally by the CLI to track translation changes between exports. Do not commit.
|
|
204
|
+
|
|
205
|
+
## Adding Translations
|
|
206
|
+
|
|
207
|
+
1. Add your translation keys to \`en-US.json\`
|
|
208
|
+
2. Run \`npx unisphere languages export\` to generate CSV files for translators
|
|
209
|
+
3. After receiving translations, run \`npx unisphere languages import\` to update the \`files/\` directory
|
|
210
|
+
4. Add the new language code to \`supported-languges.ts\`
|
|
211
|
+
|
|
212
|
+
## Usage
|
|
213
|
+
|
|
214
|
+
Components in this package use translations via the \`useTranslation\` hook:
|
|
215
|
+
|
|
216
|
+
\`\`\`typescript
|
|
217
|
+
import { useTranslation } from './use-translation';
|
|
218
|
+
|
|
219
|
+
const MyComponent = () => {
|
|
220
|
+
const { t } = useTranslation();
|
|
221
|
+
return <span>{t('myKey')}</span>;
|
|
222
|
+
};
|
|
223
|
+
\`\`\`
|
|
224
|
+
|
|
225
|
+
## CLI Commands
|
|
226
|
+
|
|
227
|
+
\`\`\`bash
|
|
228
|
+
npx unisphere languages export # Export translations to CSV for translation services
|
|
229
|
+
npx unisphere languages import # Import translated CSV files back to JSON
|
|
230
|
+
npx unisphere languages serve # Serve language files during local development
|
|
231
|
+
npx unisphere languages bundle # Bundle language files for distribution
|
|
232
|
+
\`\`\`
|
|
233
|
+
`;
|
|
234
|
+
tree.write(filePath, content);
|
|
235
|
+
devkit_1.logger.info(` ✅ Created ${filePath}`);
|
|
236
|
+
}
|
|
237
|
+
function updateUseTranslationImports(tree, sourceRoot, useTranslationPath) {
|
|
238
|
+
let updatedCount = 0;
|
|
239
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, sourceRoot, (filePath) => {
|
|
240
|
+
if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
|
|
241
|
+
return;
|
|
242
|
+
const content = tree.read(filePath, 'utf-8');
|
|
243
|
+
if (!content)
|
|
244
|
+
return;
|
|
245
|
+
// Match: import { useTranslation } from 'react-i18next';
|
|
246
|
+
const reactI18nextImport = /import\s*\{\s*useTranslation\s*\}\s*from\s*['"]react-i18next['"];?\s*\n?/;
|
|
247
|
+
if (!reactI18nextImport.test(content))
|
|
248
|
+
return;
|
|
249
|
+
// Skip the languages-provider.tsx file itself (will be deleted)
|
|
250
|
+
if (filePath.includes('languages-provider'))
|
|
251
|
+
return;
|
|
252
|
+
// Calculate relative path from this file to use-translation.tsx
|
|
253
|
+
const fileDir = path.dirname(filePath);
|
|
254
|
+
let relativePath = path.relative(fileDir, useTranslationPath);
|
|
255
|
+
// Remove .tsx extension for import
|
|
256
|
+
relativePath = relativePath.replace(/\.tsx$/, '');
|
|
257
|
+
// Ensure it starts with ./
|
|
258
|
+
if (!relativePath.startsWith('.')) {
|
|
259
|
+
relativePath = './' + relativePath;
|
|
260
|
+
}
|
|
261
|
+
const updatedContent = content.replace(reactI18nextImport, `import { useTranslation } from '${relativePath}';\n`);
|
|
262
|
+
if (updatedContent !== content) {
|
|
263
|
+
tree.write(filePath, updatedContent);
|
|
264
|
+
updatedCount++;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
if (updatedCount > 0) {
|
|
268
|
+
devkit_1.logger.info(` ✅ Updated useTranslation imports in ${updatedCount} file(s)`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function removeLanguagesProviderUsage(tree, sourceRoot) {
|
|
272
|
+
let updatedCount = 0;
|
|
273
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, sourceRoot, (filePath) => {
|
|
274
|
+
if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
|
|
275
|
+
return;
|
|
276
|
+
if (filePath.includes('languages-provider'))
|
|
277
|
+
return;
|
|
278
|
+
const content = tree.read(filePath, 'utf-8');
|
|
279
|
+
if (!content)
|
|
280
|
+
return;
|
|
281
|
+
if (!content.includes('LanguagesProvider'))
|
|
282
|
+
return;
|
|
283
|
+
let updatedContent = content;
|
|
284
|
+
// Remove LanguagesProvider import (handles various import patterns)
|
|
285
|
+
// Pattern 1: Standalone import
|
|
286
|
+
updatedContent = updatedContent.replace(/import\s*\{\s*LanguagesProvider\s*\}\s*from\s*['"][^'"]+['"];?\s*\n?/g, '');
|
|
287
|
+
// Pattern 2: Part of a multi-import (e.g., import { X, LanguagesProvider, Y } from ...)
|
|
288
|
+
updatedContent = updatedContent.replace(/,\s*LanguagesProvider\s*/g, '');
|
|
289
|
+
updatedContent = updatedContent.replace(/LanguagesProvider\s*,\s*/g, '');
|
|
290
|
+
// Remove <LanguagesProvider> wrapping (keep children)
|
|
291
|
+
// Handle: <LanguagesProvider>\n...children...\n</LanguagesProvider>
|
|
292
|
+
updatedContent = updatedContent.replace(/\s*<LanguagesProvider>\s*\n?/g, '');
|
|
293
|
+
updatedContent = updatedContent.replace(/\s*<\/LanguagesProvider>\s*\n?/g, '');
|
|
294
|
+
if (updatedContent !== content) {
|
|
295
|
+
tree.write(filePath, updatedContent);
|
|
296
|
+
updatedCount++;
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
if (updatedCount > 0) {
|
|
300
|
+
devkit_1.logger.info(` ✅ Removed LanguagesProvider from ${updatedCount} file(s)`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function deleteLanguagesProvider(tree, sourceRoot) {
|
|
304
|
+
const possiblePaths = [
|
|
305
|
+
`${sourceRoot}/src/lib/providers/languages-provider.tsx`,
|
|
306
|
+
`${sourceRoot}/src/lib/providers/languages-provider.ts`,
|
|
307
|
+
];
|
|
308
|
+
for (const filePath of possiblePaths) {
|
|
309
|
+
if (tree.exists(filePath)) {
|
|
310
|
+
tree.delete(filePath);
|
|
311
|
+
devkit_1.logger.info(` 🗑️ Deleted ${filePath}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function updateBarrelExport(tree, sourceRoot) {
|
|
316
|
+
const indexPath = `${sourceRoot}/src/index.ts`;
|
|
317
|
+
if (!tree.exists(indexPath))
|
|
318
|
+
return;
|
|
319
|
+
const content = tree.read(indexPath, 'utf-8');
|
|
320
|
+
if (!content)
|
|
321
|
+
return;
|
|
322
|
+
// Remove export of languages-provider
|
|
323
|
+
const updatedContent = content.replace(/export\s*\*\s*from\s*['"]\.\/lib\/providers\/languages-provider['"];?\s*\n?/g, '');
|
|
324
|
+
if (updatedContent !== content) {
|
|
325
|
+
tree.write(indexPath, updatedContent);
|
|
326
|
+
devkit_1.logger.info(` ✅ Removed LanguagesProvider from barrel export`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function exportUseTranslationFromBarrel(tree, sourceRoot) {
|
|
330
|
+
const indexPath = `${sourceRoot}/src/index.ts`;
|
|
331
|
+
if (!tree.exists(indexPath))
|
|
332
|
+
return;
|
|
333
|
+
const content = tree.read(indexPath, 'utf-8');
|
|
334
|
+
if (!content)
|
|
335
|
+
return;
|
|
336
|
+
// Check if already exported
|
|
337
|
+
if (content.includes('use-translation'))
|
|
338
|
+
return;
|
|
339
|
+
const exportLine = `export { useTranslation } from './lib/use-translation';\n`;
|
|
340
|
+
const updatedContent = content + exportLine;
|
|
341
|
+
tree.write(indexPath, updatedContent);
|
|
342
|
+
devkit_1.logger.info(` ✅ Added useTranslation to barrel export`);
|
|
343
|
+
}
|
|
344
|
+
// =============================================================================
|
|
345
|
+
// Step 2: Runtime Migrations
|
|
346
|
+
// =============================================================================
|
|
347
|
+
function migrateRuntimes(tree, runtimes, migratedPackages) {
|
|
348
|
+
let updatedCount = 0;
|
|
349
|
+
for (const [name, config] of Object.entries(runtimes)) {
|
|
350
|
+
const { sourceRoot } = config;
|
|
351
|
+
if (!tree.exists(sourceRoot)) {
|
|
352
|
+
devkit_1.logger.warn(` ⚠️ Runtime "${name}" source root not found: ${sourceRoot}`);
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
const runtimeFilePath = `${sourceRoot}/src/lib/runtime.tsx`;
|
|
356
|
+
if (!tree.exists(runtimeFilePath)) {
|
|
357
|
+
// Try alternative patterns
|
|
358
|
+
const altPath = `${sourceRoot}/src/lib/runtime.ts`;
|
|
359
|
+
if (!tree.exists(altPath)) {
|
|
360
|
+
devkit_1.logger.warn(` ⚠️ Runtime "${name}" has no runtime.tsx at ${runtimeFilePath}`);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
devkit_1.logger.info(` ⚡ Migrating runtime "${name}"...`);
|
|
365
|
+
// 2a. Create src/languages folder structure for runtime
|
|
366
|
+
createRuntimeLanguagesFolder(tree, sourceRoot);
|
|
367
|
+
// 2b. Create use-translation.tsx for runtime (uses 'self' as packageName)
|
|
368
|
+
const runtimeUseTranslationPath = `${sourceRoot}/src/lib/use-translation.tsx`;
|
|
369
|
+
createUseTranslationFile(tree, runtimeUseTranslationPath, 'self');
|
|
370
|
+
// 2c. Add UnisphereI18NRuntimeProxy to runtime.tsx
|
|
371
|
+
addRuntimeProxy(tree, runtimeFilePath);
|
|
372
|
+
// 2d. Remove LanguagesProvider from runtime
|
|
373
|
+
removeLanguagesProviderFromRuntime(tree, runtimeFilePath);
|
|
374
|
+
// 2e. Update useTranslation imports in runtime files
|
|
375
|
+
updateRuntimeUseTranslationImports(tree, sourceRoot, migratedPackages);
|
|
376
|
+
updatedCount++;
|
|
377
|
+
}
|
|
378
|
+
if (updatedCount > 0) {
|
|
379
|
+
devkit_1.logger.info(` ✅ Migrated ${updatedCount} runtime(s)`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function createRuntimeLanguagesFolder(tree, sourceRoot) {
|
|
383
|
+
const langDir = `${sourceRoot}/src/languages`;
|
|
384
|
+
// en-US.json
|
|
385
|
+
if (!tree.exists(`${langDir}/en-US.json`)) {
|
|
386
|
+
tree.write(`${langDir}/en-US.json`, '{}');
|
|
387
|
+
}
|
|
388
|
+
// supported-languges.ts
|
|
389
|
+
if (!tree.exists(`${langDir}/supported-languges.ts`)) {
|
|
390
|
+
tree.write(`${langDir}/supported-languges.ts`, `export const supportedLanguages: string[] = ['en-US'];\n`);
|
|
391
|
+
}
|
|
392
|
+
// files/.gitkeep
|
|
393
|
+
if (!tree.exists(`${langDir}/files/.gitkeep`)) {
|
|
394
|
+
tree.write(`${langDir}/files/.gitkeep`, '');
|
|
395
|
+
}
|
|
396
|
+
// _db/.gitignore
|
|
397
|
+
if (!tree.exists(`${langDir}/_db/.gitignore`)) {
|
|
398
|
+
tree.write(`${langDir}/_db/.gitignore`, '');
|
|
399
|
+
}
|
|
400
|
+
// README.md
|
|
401
|
+
if (!tree.exists(`${langDir}/README.md`)) {
|
|
402
|
+
createLanguagesReadme(tree, `${langDir}/README.md`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function addRuntimeProxy(tree, runtimeFilePath) {
|
|
406
|
+
if (!tree.exists(runtimeFilePath))
|
|
407
|
+
return;
|
|
408
|
+
let content = tree.read(runtimeFilePath, 'utf-8');
|
|
409
|
+
if (!content)
|
|
410
|
+
return;
|
|
411
|
+
// Check if already has the proxy
|
|
412
|
+
if (content.includes('UnisphereI18NRuntimeProxy')) {
|
|
413
|
+
devkit_1.logger.info(` ℹ️ UnisphereI18NRuntimeProxy already present`);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// Add import for UnisphereI18NRuntimeProxy
|
|
417
|
+
content = addI18nProxyImport(content);
|
|
418
|
+
// Add the proxy component inside each render method's ScopedUnisphereWorkspaceProvider
|
|
419
|
+
content = insertProxyIntoRenderMethods(content);
|
|
420
|
+
tree.write(runtimeFilePath, content);
|
|
421
|
+
devkit_1.logger.info(` ✅ Added UnisphereI18NRuntimeProxy to runtime`);
|
|
422
|
+
}
|
|
423
|
+
function addI18nProxyImport(content) {
|
|
424
|
+
// Check if @unisphere/ui-i18n-react is already imported
|
|
425
|
+
if (content.includes('@unisphere/ui-i18n-react')) {
|
|
426
|
+
// Add UnisphereI18NRuntimeProxy to existing import
|
|
427
|
+
return content.replace(/(import\s*\{[^}]*)(}\s*from\s*['"]@unisphere\/ui-i18n-react['"])/, (_, start, end) => {
|
|
428
|
+
if (start.includes('UnisphereI18NRuntimeProxy'))
|
|
429
|
+
return start + end;
|
|
430
|
+
return `${start.trimEnd()}, UnisphereI18NRuntimeProxy ${end}`;
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
// Add new import after existing @unisphere imports or at the top
|
|
434
|
+
const unisphereImportPattern = /import\s*\{[^}]*\}\s*from\s*['"]@unisphere\/[^'"]+['"];?\s*\n/g;
|
|
435
|
+
let lastMatch = null;
|
|
436
|
+
let match;
|
|
437
|
+
while ((match = unisphereImportPattern.exec(content)) !== null) {
|
|
438
|
+
lastMatch = match;
|
|
439
|
+
}
|
|
440
|
+
const importStatement = `import { UnisphereI18NRuntimeProxy } from '@unisphere/ui-i18n-react';\n`;
|
|
441
|
+
if (lastMatch) {
|
|
442
|
+
const insertPos = lastMatch.index + lastMatch[0].length;
|
|
443
|
+
return (content.slice(0, insertPos) + importStatement + content.slice(insertPos));
|
|
444
|
+
}
|
|
445
|
+
// Fallback: add after all imports
|
|
446
|
+
const lastImportMatch = content.match(/^import\s.+from\s+['"][^'"]+['"];?\s*$/gm);
|
|
447
|
+
if (lastImportMatch) {
|
|
448
|
+
const lastImport = lastImportMatch[lastImportMatch.length - 1];
|
|
449
|
+
const lastImportEnd = content.lastIndexOf(lastImport) + lastImport.length;
|
|
450
|
+
return (content.slice(0, lastImportEnd) +
|
|
451
|
+
'\n' +
|
|
452
|
+
importStatement +
|
|
453
|
+
content.slice(lastImportEnd));
|
|
454
|
+
}
|
|
455
|
+
return importStatement + content;
|
|
456
|
+
}
|
|
457
|
+
function insertProxyIntoRenderMethods(content) {
|
|
458
|
+
// Strategy: Find each render method's JSX tree and insert the proxy
|
|
459
|
+
// after the first <ScopedUnisphereWorkspaceProvider ...> opening tag.
|
|
460
|
+
// This works whether ScopedProvider wraps ThemeProvider or is inside it.
|
|
461
|
+
//
|
|
462
|
+
// Pattern we're looking for:
|
|
463
|
+
// <ScopedUnisphereWorkspaceProvider
|
|
464
|
+
// runtimeLogger={...}
|
|
465
|
+
// unisphereWorkspace={...}
|
|
466
|
+
// >
|
|
467
|
+
// <-- INSERT PROXY HERE
|
|
468
|
+
//
|
|
469
|
+
// We find each occurrence of this multi-line opening tag and insert after it.
|
|
470
|
+
const lines = content.split('\n');
|
|
471
|
+
const result = [];
|
|
472
|
+
let i = 0;
|
|
473
|
+
while (i < lines.length) {
|
|
474
|
+
result.push(lines[i]);
|
|
475
|
+
// Detect start of ScopedUnisphereWorkspaceProvider opening tag
|
|
476
|
+
if (lines[i].includes('<ScopedUnisphereWorkspaceProvider')) {
|
|
477
|
+
// Find the closing > of this opening tag (may be on same line or subsequent lines)
|
|
478
|
+
let closingLine = i;
|
|
479
|
+
// Check if tag closes on same line (self-closing or inline)
|
|
480
|
+
if (lines[i].includes('>') && !lines[i].includes('</')) {
|
|
481
|
+
closingLine = i;
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
// Look forward for the closing >
|
|
485
|
+
for (let j = i + 1; j < lines.length && j < i + 10; j++) {
|
|
486
|
+
result.push(lines[j]);
|
|
487
|
+
closingLine = j;
|
|
488
|
+
if (lines[j].trim() === '>' || lines[j].trimEnd().endsWith('>')) {
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
i = closingLine;
|
|
493
|
+
}
|
|
494
|
+
// Determine indentation for the proxy (one level deeper than the closing >)
|
|
495
|
+
const closingIndent = lines[closingLine].match(/^(\s*)/)?.[1] || '';
|
|
496
|
+
const proxyIndent = closingIndent + ' ';
|
|
497
|
+
// Insert the proxy component
|
|
498
|
+
result.push(`${proxyIndent}<UnisphereI18NRuntimeProxy`);
|
|
499
|
+
result.push(`${proxyIndent} runtimeUri={this._options.runtimeDeployedPath}`);
|
|
500
|
+
result.push(`${proxyIndent}/>`);
|
|
501
|
+
}
|
|
502
|
+
i++;
|
|
503
|
+
}
|
|
504
|
+
return result.join('\n');
|
|
505
|
+
}
|
|
506
|
+
function removeLanguagesProviderFromRuntime(tree, runtimeFilePath) {
|
|
507
|
+
if (!tree.exists(runtimeFilePath))
|
|
508
|
+
return;
|
|
509
|
+
const content = tree.read(runtimeFilePath, 'utf-8');
|
|
510
|
+
if (!content)
|
|
511
|
+
return;
|
|
512
|
+
if (!content.includes('LanguagesProvider'))
|
|
513
|
+
return;
|
|
514
|
+
let updatedContent = content;
|
|
515
|
+
// Remove LanguagesProvider from import statement
|
|
516
|
+
// Pattern: import { X, LanguagesProvider, Y } from '...'
|
|
517
|
+
// Or standalone: import { LanguagesProvider } from '...'
|
|
518
|
+
// Check if it's the only named import
|
|
519
|
+
const standaloneImport = /import\s*\{\s*LanguagesProvider\s*\}\s*from\s*['"][^'"]+['"];?\s*\n?/g;
|
|
520
|
+
if (standaloneImport.test(updatedContent)) {
|
|
521
|
+
updatedContent = updatedContent.replace(standaloneImport, '');
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
// Part of multi-import: remove with surrounding comma
|
|
525
|
+
updatedContent = updatedContent.replace(/,\s*\n?\s*LanguagesProvider/g, '');
|
|
526
|
+
updatedContent = updatedContent.replace(/LanguagesProvider\s*,\s*\n?\s*/g, '');
|
|
527
|
+
}
|
|
528
|
+
// Remove <LanguagesProvider> and </LanguagesProvider> JSX wrapping
|
|
529
|
+
updatedContent = updatedContent.replace(/(\s*)<LanguagesProvider>\s*\n?/g, '');
|
|
530
|
+
updatedContent = updatedContent.replace(/(\s*)<\/LanguagesProvider>\s*\n?/g, '');
|
|
531
|
+
if (updatedContent !== content) {
|
|
532
|
+
tree.write(runtimeFilePath, updatedContent);
|
|
533
|
+
devkit_1.logger.info(` ✅ Removed LanguagesProvider from runtime`);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
function updateRuntimeUseTranslationImports(tree, runtimeSourceRoot, migratedPackages) {
|
|
537
|
+
if (migratedPackages.length === 0)
|
|
538
|
+
return;
|
|
539
|
+
// Determine which package this runtime uses by checking the main runtime.tsx file
|
|
540
|
+
// for imports from any of our migrated packages
|
|
541
|
+
let targetPackage = null;
|
|
542
|
+
const runtimeFilePath = `${runtimeSourceRoot}/src/lib/runtime.tsx`;
|
|
543
|
+
if (tree.exists(runtimeFilePath)) {
|
|
544
|
+
const runtimeContent = tree.read(runtimeFilePath, 'utf-8') || '';
|
|
545
|
+
for (const pkg of migratedPackages) {
|
|
546
|
+
if (runtimeContent.includes(pkg.packageName)) {
|
|
547
|
+
targetPackage = pkg;
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
// If runtime doesn't import from any migrated package, check all source files
|
|
553
|
+
if (!targetPackage) {
|
|
554
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, runtimeSourceRoot, (filePath) => {
|
|
555
|
+
if (targetPackage)
|
|
556
|
+
return;
|
|
557
|
+
if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
|
|
558
|
+
return;
|
|
559
|
+
const content = tree.read(filePath, 'utf-8');
|
|
560
|
+
if (!content)
|
|
561
|
+
return;
|
|
562
|
+
for (const pkg of migratedPackages) {
|
|
563
|
+
if (content.includes(pkg.packageName)) {
|
|
564
|
+
targetPackage = pkg;
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
// Last resort: use first migrated package
|
|
571
|
+
if (!targetPackage) {
|
|
572
|
+
targetPackage = migratedPackages[0];
|
|
573
|
+
}
|
|
574
|
+
let updatedCount = 0;
|
|
575
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, runtimeSourceRoot, (filePath) => {
|
|
576
|
+
if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
|
|
577
|
+
return;
|
|
578
|
+
const content = tree.read(filePath, 'utf-8');
|
|
579
|
+
if (!content)
|
|
580
|
+
return;
|
|
581
|
+
const reactI18nextImport = /import\s*\{\s*useTranslation\s*\}\s*from\s*['"]react-i18next['"];?\s*\n?/;
|
|
582
|
+
if (!reactI18nextImport.test(content))
|
|
583
|
+
return;
|
|
584
|
+
const updatedContent = content.replace(reactI18nextImport, `import { useTranslation } from '${targetPackage.packageName}';\n`);
|
|
585
|
+
if (updatedContent !== content) {
|
|
586
|
+
tree.write(filePath, updatedContent);
|
|
587
|
+
updatedCount++;
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
if (updatedCount > 0) {
|
|
591
|
+
devkit_1.logger.info(` ✅ Updated useTranslation imports in ${updatedCount} runtime file(s)`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
// =============================================================================
|
|
595
|
+
// Step 3: Root package.json updates
|
|
596
|
+
// =============================================================================
|
|
597
|
+
function updateRootPackageJson(tree) {
|
|
598
|
+
if (!tree.exists('package.json'))
|
|
599
|
+
return;
|
|
600
|
+
const packageJson = (0, devkit_1.readJson)(tree, 'package.json');
|
|
601
|
+
const deps = packageJson.dependencies || {};
|
|
602
|
+
const devDeps = packageJson.devDependencies || {};
|
|
603
|
+
let changed = false;
|
|
604
|
+
// Remove i18next and react-i18next
|
|
605
|
+
if (deps['i18next']) {
|
|
606
|
+
delete deps['i18next'];
|
|
607
|
+
changed = true;
|
|
608
|
+
devkit_1.logger.info(' 🗑️ Removed i18next from dependencies');
|
|
609
|
+
}
|
|
610
|
+
if (deps['react-i18next']) {
|
|
611
|
+
delete deps['react-i18next'];
|
|
612
|
+
changed = true;
|
|
613
|
+
devkit_1.logger.info(' 🗑️ Removed react-i18next from dependencies');
|
|
614
|
+
}
|
|
615
|
+
if (devDeps['i18next']) {
|
|
616
|
+
delete devDeps['i18next'];
|
|
617
|
+
changed = true;
|
|
618
|
+
}
|
|
619
|
+
if (devDeps['react-i18next']) {
|
|
620
|
+
delete devDeps['react-i18next'];
|
|
621
|
+
changed = true;
|
|
622
|
+
}
|
|
623
|
+
if (changed) {
|
|
624
|
+
packageJson.dependencies = deps;
|
|
625
|
+
packageJson.devDependencies = devDeps;
|
|
626
|
+
(0, devkit_1.writeJson)(tree, 'package.json', packageJson);
|
|
627
|
+
devkit_1.logger.info(' ✅ Updated root package.json dependencies');
|
|
628
|
+
}
|
|
629
|
+
}
|
package/migrations.json
CHANGED
|
@@ -562,6 +562,14 @@
|
|
|
562
562
|
"cli": {
|
|
563
563
|
"postUpdateMessage": "✅ .github/workflows/cicd.yml updated"
|
|
564
564
|
}
|
|
565
|
+
},
|
|
566
|
+
"4.15.0-add-languages-support": {
|
|
567
|
+
"version": "4.15.0",
|
|
568
|
+
"description": "Migrates packages from i18next/react-i18next to @unisphere/ui-i18n-react with createUseTranslation pattern and adds UnisphereI18NRuntimeProxy to all runtimes",
|
|
569
|
+
"factory": "./dist/migrations/4-15-0/add-languages-support.js",
|
|
570
|
+
"cli": {
|
|
571
|
+
"postUpdateMessage": "✅ Languages support migrated to @unisphere/ui-i18n-react"
|
|
572
|
+
}
|
|
565
573
|
}
|
|
566
574
|
},
|
|
567
575
|
"packageJsonUpdates": {
|
|
@@ -997,6 +1005,21 @@
|
|
|
997
1005
|
"alwaysAddToPackageJson": false
|
|
998
1006
|
}
|
|
999
1007
|
}
|
|
1008
|
+
},
|
|
1009
|
+
"4.15.0": {
|
|
1010
|
+
"version": "4.15.0",
|
|
1011
|
+
"cli": "nx",
|
|
1012
|
+
"postUpdateMessage": "🎉 Migration to @unisphere/nx 4.15.0 completed successfully!",
|
|
1013
|
+
"packages": {
|
|
1014
|
+
"@unisphere/ui-i18n-react": {
|
|
1015
|
+
"version": "^1.70.1",
|
|
1016
|
+
"alwaysAddToPackageJson": true
|
|
1017
|
+
},
|
|
1018
|
+
"@unisphere/cli": {
|
|
1019
|
+
"version": "6.0.1",
|
|
1020
|
+
"alwaysAddToPackageJson": false
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1000
1023
|
}
|
|
1001
1024
|
}
|
|
1002
1025
|
}
|