@fluenti/cli 0.4.0-rc.1 → 0.4.0-rc.2
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/cli.cjs +4 -3
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +28 -9
- package/dist/cli.js.map +1 -1
- package/dist/migrate.d.ts +4 -0
- package/dist/migrate.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -692,7 +692,7 @@ function ke(e) {
|
|
|
692
692
|
}
|
|
693
693
|
function Ae(e, t, n) {
|
|
694
694
|
let r = [];
|
|
695
|
-
if (r.push(`You are a migration
|
|
695
|
+
if (r.push(`You are a migration tool converting a ${e.framework} project from "${e.name}" to Fluenti (@fluenti).`, "", "Tasks:", "1. Generate a `fluenti.config.ts` based on the existing i18n configuration", "2. Convert each locale/translation file to standard gettext PO format", "3. Generate unified diff patches for every source file that needs changes", "4. Generate install/uninstall commands", "", "=== TRANSLATION API RULES ===", "Fluenti provides a compile-time `t` tagged template that does NOT require useI18n():", "", " import { t } from '@fluenti/react' // or @fluenti/vue, @fluenti/solid", " const name = \"World\"", " t`Hello, ${name}!`", "", "Use `import { t }` for ALL translation calls. Only use `useI18n()` when you need:", "- `d()` / `n()` for date/number formatting", "- `setLocale()` for locale switching", "- `locale` for reading the current locale reactively", "", "=== SOURCE CODE REWRITING RULES ===", "Imports:", `- ${e.name}: remove all imports from "${e.name}" (and related packages)`, `- Add: import { t } from '@fluenti/${e.framework === "Vue" ? "vue" : e.framework === "Next.js" ? "react" : e.framework.toLowerCase()}'`, "- Only add useI18n import if d()/n()/setLocale is needed in that file", "", "Translation calls:", "- t('key') → t`Source text` (tagged template with the actual source text, not the key)", "- t('key', { name }) → t`Hello, ${name}` (interpolate directly in template)", "- $t('key') → t`Source text` (Vue template)", "- Remove useI18n()/useTranslation()/useTranslations() destructuring if only t was used", "", "Components:", "- <i18n-t keypath=\"key\"> → <Trans>Source text</Trans>", "- <Trans i18nKey=\"key\"> → <Trans>Source text</Trans>", "", "ICU syntax conversion:", "- {{variable}} (double braces) → {variable} (single braces)", "- _one/_other suffixes → ICU {count, plural, one {...} other {...}}", "- @:key references → inline the referenced text directly", "- Pipe-separated plurals → ICU plural", "", "=== PO FORMAT RULES ===", "Each PO file must have a standard header:", " msgid \"\"", " msgstr \"\"", " \"Content-Type: text/plain; charset=UTF-8\\n\"", " \"Content-Transfer-Encoding: 8bit\\n\"", " \"Language: {locale}\\n\"", "", "Message entries: msgid is the source text (English), msgstr is the translation.", "Flatten nested JSON keys: \"home.title\" → use the actual source text as msgid.", ""), n && r.push("=== MIGRATION GUIDE ===", n, ""), t.packageJson && r.push("=== package.json ===", t.packageJson, ""), t.configFiles.length > 0) {
|
|
696
696
|
r.push("=== EXISTING CONFIG FILES ===");
|
|
697
697
|
for (let e of t.configFiles) r.push(`--- ${e.path} ---`, e.content, "");
|
|
698
698
|
}
|
|
@@ -704,7 +704,7 @@ function Ae(e, t, n) {
|
|
|
704
704
|
r.push("=== SAMPLE SOURCE FILES ===");
|
|
705
705
|
for (let e of t.sampleSources) r.push(`--- ${e.path} ---`, e.content, "");
|
|
706
706
|
}
|
|
707
|
-
return r.push("", "=== OUTPUT FORMAT ===", "
|
|
707
|
+
return r.push("", "=== OUTPUT FORMAT ===", "Output ONLY the following sections. No explanations, no commentary.", "", "### FLUENTI_CONFIG", "```ts", "// Complete fluenti.config.ts", "```", "", "### LOCALE_FILES", "#### LOCALE: {locale_code}", "```po", "// Complete PO file with standard header", "```", "(repeat for each locale)", "", "### SOURCE_PATCHES", "#### FILE: {relative_file_path}", "```diff", "--- a/{file_path}", "+++ b/{file_path}", "@@ ... @@", " context line", "-removed line", "+added line", "```", "(repeat for each file that needs changes)", "", "### INSTALL_COMMANDS", "```bash", "// install + uninstall commands", "```"), r.join("\n");
|
|
708
708
|
}
|
|
709
709
|
async function je(e, t) {
|
|
710
710
|
let n = 10 * 1024 * 1024;
|
|
@@ -729,11 +729,12 @@ function Me(e) {
|
|
|
729
729
|
let t = 5e5, n = e.length > t ? e.slice(0, t) : e, r = {
|
|
730
730
|
config: void 0,
|
|
731
731
|
localeFiles: [],
|
|
732
|
+
sourcePatches: [],
|
|
732
733
|
steps: void 0,
|
|
733
734
|
installCommands: void 0
|
|
734
735
|
}, i = n.match(/### FLUENTI_CONFIG[\s\S]*?```(?:ts|typescript)?\n([\s\S]*?)```/);
|
|
735
736
|
i && (r.config = i[1].trim());
|
|
736
|
-
let a = n.match(/### LOCALE_FILES([\s\S]*?)(?=### MIGRATION_STEPS|### INSTALL_COMMANDS|$)/);
|
|
737
|
+
let a = n.match(/### LOCALE_FILES([\s\S]*?)(?=### SOURCE_PATCHES|### MIGRATION_STEPS|### INSTALL_COMMANDS|$)/);
|
|
737
738
|
if (a) {
|
|
738
739
|
let e = /#### LOCALE:\s*(\S+)\s*\n```(?:po)?\n([\s\S]*?)```/g, t;
|
|
739
740
|
for (; (t = e.exec(a[1])) !== null;) r.localeFiles.push({
|
|
@@ -741,10 +742,18 @@ function Me(e) {
|
|
|
741
742
|
content: t[2].trim()
|
|
742
743
|
});
|
|
743
744
|
}
|
|
744
|
-
let o = n.match(/###
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
745
|
+
let o = n.match(/### SOURCE_PATCHES([\s\S]*?)(?=### INSTALL_COMMANDS|$)/);
|
|
746
|
+
if (o) {
|
|
747
|
+
let e = /#### FILE:\s*(\S+)\s*\n```(?:diff)?\n([\s\S]*?)```/g, t;
|
|
748
|
+
for (; (t = e.exec(o[1])) !== null;) r.sourcePatches.push({
|
|
749
|
+
file: t[1],
|
|
750
|
+
patch: t[2].trim()
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
let s = n.match(/### MIGRATION_STEPS\s*\n([\s\S]*?)(?=### INSTALL_COMMANDS|$)/);
|
|
754
|
+
s && (r.steps = s[1].trim());
|
|
755
|
+
let c = n.match(/### INSTALL_COMMANDS[\s\S]*?```(?:bash|sh)?\n([\s\S]*?)```/);
|
|
756
|
+
return c && (r.installCommands = c[1].trim()), r;
|
|
748
757
|
}
|
|
749
758
|
async function Ne(e) {
|
|
750
759
|
let { from: t, provider: n, write: r } = e, i = De(t);
|
|
@@ -785,10 +794,20 @@ async function Ne(e) {
|
|
|
785
794
|
title: `locales/${e.locale}.po`,
|
|
786
795
|
message: e.content.length > 500 ? e.content.slice(0, 500) + "\n... (use --write to save full file)" : e.content
|
|
787
796
|
});
|
|
788
|
-
c.
|
|
797
|
+
if (c.sourcePatches.length > 0) if (r) {
|
|
798
|
+
A.log(""), A.info(`Generated ${c.sourcePatches.length} source patch(es). Apply with:`);
|
|
799
|
+
for (let e of c.sourcePatches) {
|
|
800
|
+
let t = w(`.fluenti-migrate-${e.file.replace(/[/\\]/g, "-")}.patch`), { writeFileSync: n } = await import("node:fs");
|
|
801
|
+
n(t, e.patch, "utf-8"), A.success(`Patch written: ${t}`), A.log(` patch -p1 < ${t}`);
|
|
802
|
+
}
|
|
803
|
+
} else for (let e of c.sourcePatches) A.log(""), A.box({
|
|
804
|
+
title: `Patch: ${e.file}`,
|
|
805
|
+
message: e.patch.length > 800 ? e.patch.slice(0, 800) + "\n... (use --write to save full patch)" : e.patch
|
|
806
|
+
});
|
|
807
|
+
c.steps && c.sourcePatches.length === 0 && (A.log(""), A.box({
|
|
789
808
|
title: "Migration Steps",
|
|
790
809
|
message: c.steps
|
|
791
|
-
})), !r && (c.config || c.localeFiles.length > 0) && (A.log(""), A.info("Run with --write to save generated files to disk:"), A.log(` fluenti migrate --from ${t} --write`));
|
|
810
|
+
})), !r && (c.config || c.localeFiles.length > 0 || c.sourcePatches.length > 0) && (A.log(""), A.info("Run with --write to save generated files and patches to disk:"), A.log(` fluenti migrate --from ${t} --write`));
|
|
792
811
|
}
|
|
793
812
|
//#endregion
|
|
794
813
|
//#region src/init.ts
|