glotfile 0.8.9 → 1.0.1
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 +1 -1
- package/dist/server/cli.js +365 -138
- package/dist/server/server.js +327 -120
- package/dist/ui/assets/{index-B64rdzp7.js → index-5Imdw0oX.js} +48 -5
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
package/dist/server/server.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Hono as Hono2 } from "hono";
|
|
3
3
|
import { serve } from "@hono/node-server";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
-
import { dirname as dirname4, join as
|
|
5
|
+
import { dirname as dirname4, join as join19, resolve as resolve10, extname as extname3, sep as sep3 } from "path";
|
|
6
6
|
import { readFile, stat } from "fs/promises";
|
|
7
7
|
import { createServer } from "net";
|
|
8
8
|
import open from "open";
|
|
@@ -959,7 +959,7 @@ var PREFIX_PATTERNS = {
|
|
|
959
959
|
/(?<!\.)(?<![a-zA-Z0-9_$])\bt\s*\(\s*`([^`$]*)\$\{/g
|
|
960
960
|
]
|
|
961
961
|
};
|
|
962
|
-
var CACHE_VERSION =
|
|
962
|
+
var CACHE_VERSION = 8;
|
|
963
963
|
var EXT_SCANNER = {
|
|
964
964
|
".php": "laravel",
|
|
965
965
|
".vue": "js-i18n",
|
|
@@ -1031,6 +1031,73 @@ function customPatterns(opts) {
|
|
|
1031
1031
|
}
|
|
1032
1032
|
return out;
|
|
1033
1033
|
}
|
|
1034
|
+
var NEXT_INTL_IMPORT = /(?:from\s*|require\(\s*)['"]next-intl(?:\/[\w-]+)?['"]/;
|
|
1035
|
+
function isNextIntlFile(content) {
|
|
1036
|
+
return NEXT_INTL_IMPORT.test(content);
|
|
1037
|
+
}
|
|
1038
|
+
var NI_BIND = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:await\s+)?(?:useTranslations|getTranslations)\s*\(\s*(?:['"]([^'"]*)['"])?\s*\)/g;
|
|
1039
|
+
var NI_BIND_OBJ = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:await\s+)?getTranslations\s*\(\s*\{[^}]*?\bnamespace\s*:\s*['"]([^'"]+)['"][^}]*?\}\s*\)/g;
|
|
1040
|
+
var NI_METHOD = "(?:\\.(?:rich|markup|raw|has))?";
|
|
1041
|
+
function nextIntlBindings(content) {
|
|
1042
|
+
const out = [];
|
|
1043
|
+
for (const m of content.matchAll(NI_BIND)) out.push({ name: m[1], ns: m[2] ?? "", index: m.index });
|
|
1044
|
+
for (const m of content.matchAll(NI_BIND_OBJ)) out.push({ name: m[1], ns: m[2], index: m.index });
|
|
1045
|
+
return out;
|
|
1046
|
+
}
|
|
1047
|
+
function nsForBindingAt(bindings, name, index) {
|
|
1048
|
+
let best = null;
|
|
1049
|
+
for (const b of bindings) {
|
|
1050
|
+
if (b.name === name && b.index < index && (!best || b.index > best.index)) best = b;
|
|
1051
|
+
}
|
|
1052
|
+
return best ? best.ns : null;
|
|
1053
|
+
}
|
|
1054
|
+
function joinKey(ns, rel) {
|
|
1055
|
+
return ns ? `${ns}.${rel}` : rel;
|
|
1056
|
+
}
|
|
1057
|
+
function uniqueBindingNames(bindings) {
|
|
1058
|
+
return [...new Set(bindings.map((b) => b.name))];
|
|
1059
|
+
}
|
|
1060
|
+
function nextIntlRefMatches(content) {
|
|
1061
|
+
const bindings = nextIntlBindings(content);
|
|
1062
|
+
const out = [];
|
|
1063
|
+
for (const name of uniqueBindingNames(bindings)) {
|
|
1064
|
+
const re = new RegExp(
|
|
1065
|
+
`\\b${escapeRe2(name)}${NI_METHOD}\\s*\\(\\s*(?:'([^'\\n]+)'|"([^"\\n]+)"|\`([^\`$\\n]+)\`)`,
|
|
1066
|
+
"g"
|
|
1067
|
+
);
|
|
1068
|
+
let m;
|
|
1069
|
+
while ((m = re.exec(content)) !== null) {
|
|
1070
|
+
const ns = nsForBindingAt(bindings, name, m.index);
|
|
1071
|
+
if (ns === null) continue;
|
|
1072
|
+
out.push({ key: joinKey(ns, m[1] ?? m[2] ?? m[3]), index: m.index });
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
return out;
|
|
1076
|
+
}
|
|
1077
|
+
function nextIntlPrefixMatches(content) {
|
|
1078
|
+
const bindings = nextIntlBindings(content);
|
|
1079
|
+
const out = [];
|
|
1080
|
+
for (const name of uniqueBindingNames(bindings)) {
|
|
1081
|
+
const ev = escapeRe2(name);
|
|
1082
|
+
const headConcat = new RegExp(`\\b${ev}${NI_METHOD}\\s*\\(\\s*(?:'([^'\\n]*)'|"([^"\\n]*)")\\s*\\+`, "g");
|
|
1083
|
+
const headTemplate = new RegExp(`\\b${ev}${NI_METHOD}\\s*\\(\\s*\`([^\`$\\n]*)\\$\\{`, "g");
|
|
1084
|
+
const dynamicArg = new RegExp(`\\b${ev}${NI_METHOD}\\s*\\(\\s*[A-Za-z_$][\\w$.]*\\s*[),]`, "g");
|
|
1085
|
+
let m;
|
|
1086
|
+
for (const re of [headConcat, headTemplate]) {
|
|
1087
|
+
while ((m = re.exec(content)) !== null) {
|
|
1088
|
+
const ns = nsForBindingAt(bindings, name, m.index);
|
|
1089
|
+
if (ns === null) continue;
|
|
1090
|
+
out.push({ prefix: joinKey(ns, m[1] ?? m[2] ?? ""), index: m.index });
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
while ((m = dynamicArg.exec(content)) !== null) {
|
|
1094
|
+
const ns = nsForBindingAt(bindings, name, m.index);
|
|
1095
|
+
if (!ns) continue;
|
|
1096
|
+
out.push({ prefix: `${ns}.`, index: m.index });
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return out;
|
|
1100
|
+
}
|
|
1034
1101
|
function lineStartOffsets(content) {
|
|
1035
1102
|
const starts = [0];
|
|
1036
1103
|
let idx = content.indexOf("\n");
|
|
@@ -1051,49 +1118,56 @@ function offsetToLineCol(starts, offset) {
|
|
|
1051
1118
|
return { line: lo + 1, col: offset - starts[lo] + 1 };
|
|
1052
1119
|
}
|
|
1053
1120
|
function extractRefs(content, scanner, opts) {
|
|
1054
|
-
const
|
|
1055
|
-
const
|
|
1056
|
-
if (patterns.length === 0) return [];
|
|
1121
|
+
const useNextIntl = scanner === "next-intl" || scanner === "js-i18n" && isNextIntlFile(content);
|
|
1122
|
+
const effScanner = useNextIntl ? "next-intl" : scanner;
|
|
1057
1123
|
const starts = lineStartOffsets(content);
|
|
1058
1124
|
const result = [];
|
|
1059
1125
|
const seen = /* @__PURE__ */ new Set();
|
|
1060
|
-
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
const { line, col } = offsetToLineCol(starts, m.index);
|
|
1067
|
-
const dedup = `${line}:${col}:${key}`;
|
|
1068
|
-
if (!seen.has(dedup)) {
|
|
1069
|
-
seen.add(dedup);
|
|
1070
|
-
result.push({ key, line, col, scanner });
|
|
1071
|
-
}
|
|
1126
|
+
const push = (key, index) => {
|
|
1127
|
+
const { line, col } = offsetToLineCol(starts, index);
|
|
1128
|
+
const dedup = `${line}:${col}:${key}`;
|
|
1129
|
+
if (!seen.has(dedup)) {
|
|
1130
|
+
seen.add(dedup);
|
|
1131
|
+
result.push({ key, line, col, scanner: effScanner });
|
|
1072
1132
|
}
|
|
1133
|
+
};
|
|
1134
|
+
if (useNextIntl) {
|
|
1135
|
+
for (const r of nextIntlRefMatches(content)) push(r.key, r.index);
|
|
1136
|
+
} else {
|
|
1137
|
+
const base = scanner === "flutter" ? flutterPatterns(content, opts) : PATTERNS[scanner] ?? [];
|
|
1138
|
+
for (const pattern of base) eachMatch(content, pattern, push);
|
|
1073
1139
|
}
|
|
1140
|
+
for (const pattern of customPatterns(opts)) eachMatch(content, pattern, push);
|
|
1074
1141
|
result.sort((a, b) => a.line - b.line || a.col - b.col);
|
|
1075
1142
|
return result;
|
|
1076
1143
|
}
|
|
1144
|
+
function eachMatch(content, pattern, fn) {
|
|
1145
|
+
const re = new RegExp(pattern.source, "g");
|
|
1146
|
+
let m;
|
|
1147
|
+
while ((m = re.exec(content)) !== null) {
|
|
1148
|
+
if (m.index === re.lastIndex) re.lastIndex++;
|
|
1149
|
+
fn(m[1], m.index);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1077
1152
|
function extractPrefixes(content, scanner) {
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1153
|
+
const useNextIntl = scanner === "next-intl" || scanner === "js-i18n" && isNextIntlFile(content);
|
|
1154
|
+
const effScanner = useNextIntl ? "next-intl" : scanner;
|
|
1080
1155
|
const starts = lineStartOffsets(content);
|
|
1081
1156
|
const result = [];
|
|
1082
1157
|
const seen = /* @__PURE__ */ new Set();
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
const { line, col } = offsetToLineCol(starts, m.index);
|
|
1091
|
-
const dedup = `${line}:${col}:${prefix}`;
|
|
1092
|
-
if (!seen.has(dedup)) {
|
|
1093
|
-
seen.add(dedup);
|
|
1094
|
-
result.push({ prefix, line, col, scanner });
|
|
1095
|
-
}
|
|
1158
|
+
const push = (prefix, index) => {
|
|
1159
|
+
if (!prefix) return;
|
|
1160
|
+
const { line, col } = offsetToLineCol(starts, index);
|
|
1161
|
+
const dedup = `${line}:${col}:${prefix}`;
|
|
1162
|
+
if (!seen.has(dedup)) {
|
|
1163
|
+
seen.add(dedup);
|
|
1164
|
+
result.push({ prefix, line, col, scanner: effScanner });
|
|
1096
1165
|
}
|
|
1166
|
+
};
|
|
1167
|
+
if (useNextIntl) {
|
|
1168
|
+
for (const p of nextIntlPrefixMatches(content)) push(p.prefix, p.index);
|
|
1169
|
+
} else {
|
|
1170
|
+
for (const pattern of PREFIX_PATTERNS[scanner] ?? []) eachMatch(content, pattern, push);
|
|
1097
1171
|
}
|
|
1098
1172
|
result.sort((a, b) => a.line - b.line || a.col - b.col);
|
|
1099
1173
|
return result;
|
|
@@ -2696,6 +2770,60 @@ var vueI18nJson = {
|
|
|
2696
2770
|
}
|
|
2697
2771
|
};
|
|
2698
2772
|
|
|
2773
|
+
// src/server/adapters/next-intl-json.ts
|
|
2774
|
+
var DEFAULT_LOCALE_CASE8 = "lower-hyphen";
|
|
2775
|
+
var nextIntlJson = {
|
|
2776
|
+
name: "next-intl-json",
|
|
2777
|
+
capabilities: {
|
|
2778
|
+
plural: "native",
|
|
2779
|
+
select: "native",
|
|
2780
|
+
nesting: "both",
|
|
2781
|
+
metadata: false,
|
|
2782
|
+
placeholderStyle: "icu",
|
|
2783
|
+
fileGrouping: "per-locale"
|
|
2784
|
+
},
|
|
2785
|
+
defaultLocaleCase: DEFAULT_LOCALE_CASE8,
|
|
2786
|
+
export(state, output) {
|
|
2787
|
+
const files = [];
|
|
2788
|
+
const warnings = [];
|
|
2789
|
+
warnings.push(...localeCollisionWarnings(output, state.config.locales, DEFAULT_LOCALE_CASE8));
|
|
2790
|
+
const { indent, finalNewline } = resolveFormat(state, output);
|
|
2791
|
+
const fmt = { indent, sortKeys: true, finalNewline };
|
|
2792
|
+
const emptyAs = resolveEmptyAs(output, "omit");
|
|
2793
|
+
const flatOutput = output.style === "flat";
|
|
2794
|
+
for (const locale of state.config.locales) {
|
|
2795
|
+
const flat = {};
|
|
2796
|
+
for (const [key, entry] of Object.entries(state.keys)) {
|
|
2797
|
+
if (entry.plural) {
|
|
2798
|
+
const forms = resolveForms(entry, locale, state.config.sourceLocale, emptyAs);
|
|
2799
|
+
if (!forms) continue;
|
|
2800
|
+
flat[key] = formsToIcu(entry.plural.arg, forms);
|
|
2801
|
+
} else {
|
|
2802
|
+
const raw = resolveScalar(entry, locale, state.config.sourceLocale, emptyAs);
|
|
2803
|
+
if (raw === null) continue;
|
|
2804
|
+
flat[key] = raw;
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
let payload = flat;
|
|
2808
|
+
if (!flatOutput) {
|
|
2809
|
+
const { tree, collisions } = nestKeys(flat);
|
|
2810
|
+
for (const key of collisions) {
|
|
2811
|
+
warnings.push({
|
|
2812
|
+
code: "key-collision",
|
|
2813
|
+
key,
|
|
2814
|
+
locale,
|
|
2815
|
+
message: "key is both a leaf and a parent; dropped from nested output"
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
payload = tree;
|
|
2819
|
+
}
|
|
2820
|
+
files.push({ path: resolvePath(output.path, resolveLocaleToken(output, locale, DEFAULT_LOCALE_CASE8)), contents: serializeJson(payload, fmt) });
|
|
2821
|
+
}
|
|
2822
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
2823
|
+
return { files, warnings };
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
|
|
2699
2827
|
// src/server/adapters/angular-xliff.ts
|
|
2700
2828
|
function xmlEscape2(s) {
|
|
2701
2829
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -2751,7 +2879,7 @@ function renderEmbeddedIcu(value) {
|
|
|
2751
2879
|
function renderScalar(value, ids, placeholders) {
|
|
2752
2880
|
return isIcuPluralOrSelect(value) ? renderEmbeddedIcu(value) : renderInterpolations(value, ids, placeholders);
|
|
2753
2881
|
}
|
|
2754
|
-
var
|
|
2882
|
+
var DEFAULT_LOCALE_CASE9 = "bcp47-hyphen";
|
|
2755
2883
|
var angularXliff = {
|
|
2756
2884
|
name: "angular-xliff",
|
|
2757
2885
|
capabilities: {
|
|
@@ -2762,18 +2890,18 @@ var angularXliff = {
|
|
|
2762
2890
|
placeholderStyle: "icu",
|
|
2763
2891
|
fileGrouping: "per-locale"
|
|
2764
2892
|
},
|
|
2765
|
-
defaultLocaleCase:
|
|
2893
|
+
defaultLocaleCase: DEFAULT_LOCALE_CASE9,
|
|
2766
2894
|
export(state, output) {
|
|
2767
2895
|
const files = [];
|
|
2768
2896
|
const warnings = [];
|
|
2769
|
-
warnings.push(...localeCollisionWarnings(output, state.config.locales,
|
|
2897
|
+
warnings.push(...localeCollisionWarnings(output, state.config.locales, DEFAULT_LOCALE_CASE9));
|
|
2770
2898
|
const sourceLocale = state.config.sourceLocale;
|
|
2771
|
-
const sourceToken = resolveLocaleToken(output, sourceLocale,
|
|
2899
|
+
const sourceToken = resolveLocaleToken(output, sourceLocale, DEFAULT_LOCALE_CASE9);
|
|
2772
2900
|
const emptyAs = resolveEmptyAs(output, "source");
|
|
2773
2901
|
const keys = Object.keys(state.keys).sort();
|
|
2774
2902
|
for (const locale of state.config.locales) {
|
|
2775
2903
|
if (output.skipSourceLocale && locale === sourceLocale) continue;
|
|
2776
|
-
const token = resolveLocaleToken(output, locale,
|
|
2904
|
+
const token = resolveLocaleToken(output, locale, DEFAULT_LOCALE_CASE9);
|
|
2777
2905
|
const units = [];
|
|
2778
2906
|
for (const key of keys) {
|
|
2779
2907
|
const entry = state.keys[key];
|
|
@@ -2837,7 +2965,7 @@ function yamlMap(node, indent, level) {
|
|
|
2837
2965
|
}
|
|
2838
2966
|
return lines;
|
|
2839
2967
|
}
|
|
2840
|
-
var
|
|
2968
|
+
var DEFAULT_LOCALE_CASE10 = "bcp47-hyphen";
|
|
2841
2969
|
var railsYaml = {
|
|
2842
2970
|
name: "rails-yaml",
|
|
2843
2971
|
capabilities: {
|
|
@@ -2848,10 +2976,10 @@ var railsYaml = {
|
|
|
2848
2976
|
placeholderStyle: "named",
|
|
2849
2977
|
fileGrouping: "per-locale"
|
|
2850
2978
|
},
|
|
2851
|
-
defaultLocaleCase:
|
|
2979
|
+
defaultLocaleCase: DEFAULT_LOCALE_CASE10,
|
|
2852
2980
|
export(state, output) {
|
|
2853
2981
|
const warnings = [];
|
|
2854
|
-
warnings.push(...localeCollisionWarnings(output, state.config.locales,
|
|
2982
|
+
warnings.push(...localeCollisionWarnings(output, state.config.locales, DEFAULT_LOCALE_CASE10));
|
|
2855
2983
|
const { indent, finalNewline } = resolveFormat(state, output);
|
|
2856
2984
|
const emptyAs = resolveEmptyAs(output, "omit");
|
|
2857
2985
|
const files = [];
|
|
@@ -2883,7 +3011,7 @@ var railsYaml = {
|
|
|
2883
3011
|
for (const c of collisions) {
|
|
2884
3012
|
warnings.push({ code: "key-collision", key: c, locale, message: "key is both a leaf and a parent; dropped from nested output" });
|
|
2885
3013
|
}
|
|
2886
|
-
const token = resolveLocaleToken(output, locale,
|
|
3014
|
+
const token = resolveLocaleToken(output, locale, DEFAULT_LOCALE_CASE10);
|
|
2887
3015
|
const body = [`${yamlKey(token)}:`, ...yamlMap(nested, indent, 1)].join("\n");
|
|
2888
3016
|
files.push({ path: resolvePath(output.path, token), contents: finalNewline ? body + "\n" : body });
|
|
2889
3017
|
}
|
|
@@ -2926,6 +3054,7 @@ function getRegistry() {
|
|
|
2926
3054
|
[appleStringsdict.name]: appleStringsdict,
|
|
2927
3055
|
[appleStrings.name]: appleStrings,
|
|
2928
3056
|
[vueI18nJson.name]: vueI18nJson,
|
|
3057
|
+
[nextIntlJson.name]: nextIntlJson,
|
|
2929
3058
|
[angularXliff.name]: angularXliff,
|
|
2930
3059
|
[railsYaml.name]: railsYaml
|
|
2931
3060
|
};
|
|
@@ -2955,7 +3084,7 @@ function checkOutputs(state, root) {
|
|
|
2955
3084
|
}
|
|
2956
3085
|
|
|
2957
3086
|
// src/server/api.ts
|
|
2958
|
-
import { readFileSync as
|
|
3087
|
+
import { readFileSync as readFileSync24, existsSync as existsSync13, readdirSync as readdirSync16, statSync as statSync10, rmSync as rmSync6 } from "fs";
|
|
2959
3088
|
import { dirname as dirname3, resolve as resolve9, basename, relative as relative4, sep as sep2 } from "path";
|
|
2960
3089
|
|
|
2961
3090
|
// src/server/ai/anthropic.ts
|
|
@@ -4480,6 +4609,47 @@ function detectVue(root, forced = false) {
|
|
|
4480
4609
|
}
|
|
4481
4610
|
return null;
|
|
4482
4611
|
}
|
|
4612
|
+
var NEXT_INTL_CONFIG_CANDIDATES = ["src/i18n/request.ts", "i18n/request.ts", "src/i18n/request.js", "i18n/request.js"];
|
|
4613
|
+
var NEXT_INTL_ROUTING_CANDIDATES = ["src/i18n/routing.ts", "i18n/routing.ts", "src/i18n/routing.js", "i18n/routing.js"];
|
|
4614
|
+
var NEXT_INTL_DIR_CANDIDATES = ["messages", "src/messages", "locales", "src/locales", "src/i18n/messages"];
|
|
4615
|
+
function hasNextIntlSignal(root) {
|
|
4616
|
+
if (NEXT_INTL_CONFIG_CANDIDATES.some((rel) => existsSync11(join6(root, rel)))) return true;
|
|
4617
|
+
try {
|
|
4618
|
+
const pkg = JSON.parse(readFileSync11(join6(root, "package.json"), "utf8"));
|
|
4619
|
+
if (pkg.dependencies?.["next-intl"] || pkg.devDependencies?.["next-intl"]) return true;
|
|
4620
|
+
} catch {
|
|
4621
|
+
}
|
|
4622
|
+
return false;
|
|
4623
|
+
}
|
|
4624
|
+
function nextIntlDefaultLocale(root) {
|
|
4625
|
+
for (const rel of NEXT_INTL_ROUTING_CANDIDATES) {
|
|
4626
|
+
try {
|
|
4627
|
+
const m = readFileSync11(join6(root, rel), "utf8").match(/defaultLocale\s*:\s*['"]([^'"]+)['"]/);
|
|
4628
|
+
if (m) return m[1];
|
|
4629
|
+
} catch {
|
|
4630
|
+
}
|
|
4631
|
+
}
|
|
4632
|
+
return void 0;
|
|
4633
|
+
}
|
|
4634
|
+
function detectNextIntl(root, forced = false) {
|
|
4635
|
+
if (!forced && !hasNextIntlSignal(root)) return null;
|
|
4636
|
+
for (const rel of NEXT_INTL_DIR_CANDIDATES) {
|
|
4637
|
+
const localeRoot = join6(root, rel);
|
|
4638
|
+
if (!safeIsDir(localeRoot)) continue;
|
|
4639
|
+
const locales = readdirSync3(localeRoot).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5)).filter((l) => LOCALE_RE.test(l));
|
|
4640
|
+
if (locales.length === 0) continue;
|
|
4641
|
+
const def = nextIntlDefaultLocale(root);
|
|
4642
|
+
const sourceLocale = def && locales.includes(def) ? def : pickSource(locales, (loc) => {
|
|
4643
|
+
try {
|
|
4644
|
+
return statSync3(join6(localeRoot, `${loc}.json`)).size;
|
|
4645
|
+
} catch {
|
|
4646
|
+
return 0;
|
|
4647
|
+
}
|
|
4648
|
+
});
|
|
4649
|
+
return { format: "next-intl-json", localeRoot, locales, sourceLocale };
|
|
4650
|
+
}
|
|
4651
|
+
return null;
|
|
4652
|
+
}
|
|
4483
4653
|
function detectArb(root) {
|
|
4484
4654
|
for (const rel of ["lib/l10n", "l10n", "lib/src/l10n"]) {
|
|
4485
4655
|
const localeRoot = join6(root, rel);
|
|
@@ -4626,6 +4796,7 @@ function detectAppleStringsdict(root) {
|
|
|
4626
4796
|
}
|
|
4627
4797
|
var DETECTORS = [
|
|
4628
4798
|
detectLaravel,
|
|
4799
|
+
detectNextIntl,
|
|
4629
4800
|
detectVue,
|
|
4630
4801
|
detectArb,
|
|
4631
4802
|
detectApple,
|
|
@@ -4637,6 +4808,7 @@ var DETECTORS = [
|
|
|
4637
4808
|
];
|
|
4638
4809
|
var BY_FORMAT = {
|
|
4639
4810
|
"laravel-php": detectLaravel,
|
|
4811
|
+
"next-intl-json": (root) => detectNextIntl(root, true),
|
|
4640
4812
|
"vue-i18n-json": (root) => detectVue(root, true),
|
|
4641
4813
|
"flutter-arb": detectArb,
|
|
4642
4814
|
"apple-strings": detectApple,
|
|
@@ -4717,9 +4889,40 @@ var vueI18nJson2 = {
|
|
|
4717
4889
|
}
|
|
4718
4890
|
};
|
|
4719
4891
|
|
|
4892
|
+
// src/server/import/parsers/next-intl-json.ts
|
|
4893
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync13 } from "fs";
|
|
4894
|
+
import { join as join8 } from "path";
|
|
4895
|
+
var LOCALE_RE3 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/;
|
|
4896
|
+
var nextIntlJson2 = {
|
|
4897
|
+
name: "next-intl-json",
|
|
4898
|
+
parse(localeRoot, opts) {
|
|
4899
|
+
const warnings = [];
|
|
4900
|
+
const keys = {};
|
|
4901
|
+
const locales = [];
|
|
4902
|
+
for (const file of readdirSync5(localeRoot).sort()) {
|
|
4903
|
+
if (!file.endsWith(".json")) continue;
|
|
4904
|
+
const locale = file.slice(0, -".json".length);
|
|
4905
|
+
if (!LOCALE_RE3.test(locale)) continue;
|
|
4906
|
+
if (opts?.locales && !opts.locales.includes(locale)) continue;
|
|
4907
|
+
let data;
|
|
4908
|
+
try {
|
|
4909
|
+
data = JSON.parse(readFileSync13(join8(localeRoot, file), "utf8"));
|
|
4910
|
+
} catch (e) {
|
|
4911
|
+
warnings.push(`next-intl-json: failed to parse ${file}: ${e.message}`);
|
|
4912
|
+
continue;
|
|
4913
|
+
}
|
|
4914
|
+
if (!locales.includes(locale)) locales.push(locale);
|
|
4915
|
+
for (const [key, value] of Object.entries(flattenObject(data, "", warnings))) {
|
|
4916
|
+
(keys[key] ??= { values: {} }).values[locale] = value;
|
|
4917
|
+
}
|
|
4918
|
+
}
|
|
4919
|
+
return { locales, keys, warnings };
|
|
4920
|
+
}
|
|
4921
|
+
};
|
|
4922
|
+
|
|
4720
4923
|
// src/server/import/parsers/laravel-php.ts
|
|
4721
|
-
import { readdirSync as
|
|
4722
|
-
import { join as
|
|
4924
|
+
import { readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
4925
|
+
import { join as join9, relative as relative2 } from "path";
|
|
4723
4926
|
import { execFileSync } from "child_process";
|
|
4724
4927
|
|
|
4725
4928
|
// src/server/import/placeholders.ts
|
|
@@ -4735,13 +4938,13 @@ function railsToCanonical(value) {
|
|
|
4735
4938
|
|
|
4736
4939
|
// src/server/import/parsers/laravel-php.ts
|
|
4737
4940
|
function listDirs2(dir) {
|
|
4738
|
-
return
|
|
4941
|
+
return readdirSync6(dir).filter((e) => statSync4(join9(dir, e)).isDirectory());
|
|
4739
4942
|
}
|
|
4740
4943
|
function listPhpFiles(dir) {
|
|
4741
4944
|
const out = [];
|
|
4742
4945
|
const walk = (d) => {
|
|
4743
|
-
for (const e of
|
|
4744
|
-
const full =
|
|
4946
|
+
for (const e of readdirSync6(d)) {
|
|
4947
|
+
const full = join9(d, e);
|
|
4745
4948
|
if (statSync4(full).isDirectory()) walk(full);
|
|
4746
4949
|
else if (e.endsWith(".php")) out.push(full);
|
|
4747
4950
|
}
|
|
@@ -4778,7 +4981,7 @@ var laravelPhp2 = {
|
|
|
4778
4981
|
for (const locale of listDirs2(localeRoot).sort()) {
|
|
4779
4982
|
if (locale === "vendor") continue;
|
|
4780
4983
|
if (opts?.locales && !opts.locales.includes(locale)) continue;
|
|
4781
|
-
const localeDir =
|
|
4984
|
+
const localeDir = join9(localeRoot, locale);
|
|
4782
4985
|
locales.push(locale);
|
|
4783
4986
|
for (const file of listPhpFiles(localeDir)) {
|
|
4784
4987
|
const group = relative2(localeDir, file).replace(/\\/g, "/").replace(/\.php$/, "");
|
|
@@ -4801,15 +5004,15 @@ var laravelPhp2 = {
|
|
|
4801
5004
|
};
|
|
4802
5005
|
|
|
4803
5006
|
// src/server/import/parsers/flutter-arb.ts
|
|
4804
|
-
import { readdirSync as
|
|
4805
|
-
import { join as
|
|
4806
|
-
var
|
|
5007
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync14 } from "fs";
|
|
5008
|
+
import { join as join10 } from "path";
|
|
5009
|
+
var LOCALE_RE4 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/;
|
|
4807
5010
|
function localeFromArbName(file) {
|
|
4808
5011
|
const m = file.match(/^(.+)\.arb$/);
|
|
4809
5012
|
if (!m) return null;
|
|
4810
5013
|
let locale = m[1];
|
|
4811
5014
|
if (locale.startsWith("app_")) locale = locale.slice(4);
|
|
4812
|
-
return
|
|
5015
|
+
return LOCALE_RE4.test(locale) ? locale : null;
|
|
4813
5016
|
}
|
|
4814
5017
|
function placeholderMeta(raw) {
|
|
4815
5018
|
if (!raw || typeof raw !== "object") return void 0;
|
|
@@ -4831,14 +5034,14 @@ var flutterArb2 = {
|
|
|
4831
5034
|
const warnings = [];
|
|
4832
5035
|
const keys = {};
|
|
4833
5036
|
const locales = [];
|
|
4834
|
-
for (const file of
|
|
5037
|
+
for (const file of readdirSync7(localeRoot).sort()) {
|
|
4835
5038
|
if (!file.endsWith(".arb")) continue;
|
|
4836
5039
|
const locale = localeFromArbName(file);
|
|
4837
5040
|
if (!locale) continue;
|
|
4838
5041
|
if (opts?.locales && !opts.locales.includes(locale)) continue;
|
|
4839
5042
|
let data;
|
|
4840
5043
|
try {
|
|
4841
|
-
data = JSON.parse(
|
|
5044
|
+
data = JSON.parse(readFileSync14(join10(localeRoot, file), "utf8"));
|
|
4842
5045
|
} catch (e) {
|
|
4843
5046
|
warnings.push(`flutter-arb: failed to parse ${file}: ${e.message}`);
|
|
4844
5047
|
continue;
|
|
@@ -4863,14 +5066,14 @@ var flutterArb2 = {
|
|
|
4863
5066
|
};
|
|
4864
5067
|
|
|
4865
5068
|
// src/server/import/parsers/apple-strings.ts
|
|
4866
|
-
import { readdirSync as
|
|
4867
|
-
import { join as
|
|
4868
|
-
var
|
|
5069
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync15, statSync as statSync5 } from "fs";
|
|
5070
|
+
import { join as join11 } from "path";
|
|
5071
|
+
var LOCALE_RE5 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/;
|
|
4869
5072
|
var TABLE = "Localizable.strings";
|
|
4870
5073
|
function localeFromLproj(dir) {
|
|
4871
5074
|
const m = dir.match(/^(.+)\.lproj$/);
|
|
4872
5075
|
if (!m) return null;
|
|
4873
|
-
return
|
|
5076
|
+
return LOCALE_RE5.test(m[1]) ? m[1] : null;
|
|
4874
5077
|
}
|
|
4875
5078
|
function printfToCanonical(s) {
|
|
4876
5079
|
return s.replace(/%%/g, "%");
|
|
@@ -4976,20 +5179,20 @@ var appleStrings2 = {
|
|
|
4976
5179
|
const warnings = [];
|
|
4977
5180
|
const keys = {};
|
|
4978
5181
|
const locales = [];
|
|
4979
|
-
for (const dir of
|
|
5182
|
+
for (const dir of readdirSync8(localeRoot).sort()) {
|
|
4980
5183
|
const locale = localeFromLproj(dir);
|
|
4981
5184
|
if (!locale) continue;
|
|
4982
5185
|
if (opts?.locales && !opts.locales.includes(locale)) continue;
|
|
4983
|
-
const file =
|
|
5186
|
+
const file = join11(localeRoot, dir, TABLE);
|
|
4984
5187
|
let text;
|
|
4985
5188
|
try {
|
|
4986
5189
|
if (!statSync5(file).isFile()) continue;
|
|
4987
|
-
text =
|
|
5190
|
+
text = readFileSync15(file, "utf8");
|
|
4988
5191
|
} catch {
|
|
4989
5192
|
continue;
|
|
4990
5193
|
}
|
|
4991
5194
|
locales.push(locale);
|
|
4992
|
-
const others =
|
|
5195
|
+
const others = readdirSync8(join11(localeRoot, dir)).filter((f) => f.endsWith(".strings") && f !== TABLE);
|
|
4993
5196
|
if (others.length) {
|
|
4994
5197
|
warnings.push(`apple-strings: ${dir} has other .strings tables (${others.join(", ")}); only ${TABLE} is imported`);
|
|
4995
5198
|
}
|
|
@@ -5002,9 +5205,9 @@ var appleStrings2 = {
|
|
|
5002
5205
|
};
|
|
5003
5206
|
|
|
5004
5207
|
// src/server/import/parsers/angular-xliff.ts
|
|
5005
|
-
import { readdirSync as
|
|
5006
|
-
import { join as
|
|
5007
|
-
var
|
|
5208
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync16 } from "fs";
|
|
5209
|
+
import { join as join12 } from "path";
|
|
5210
|
+
var LOCALE_RE6 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/;
|
|
5008
5211
|
var FILE_RE = /^messages(?:\.(.+))?\.xlf$/;
|
|
5009
5212
|
function decodeEntities(s) {
|
|
5010
5213
|
return s.replace(/&#x([0-9a-fA-F]+);/g, (_, h) => String.fromCodePoint(parseInt(h, 16))).replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(Number(d))).replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
@@ -5064,13 +5267,13 @@ var angularXliff2 = {
|
|
|
5064
5267
|
const seen = (loc) => {
|
|
5065
5268
|
if (!locales.includes(loc)) locales.push(loc);
|
|
5066
5269
|
};
|
|
5067
|
-
const files =
|
|
5270
|
+
const files = readdirSync9(localeRoot).filter((f) => FILE_RE.test(f)).sort((a, b) => (a === "messages.xlf" ? -1 : 0) - (b === "messages.xlf" ? -1 : 0) || a.localeCompare(b));
|
|
5068
5271
|
for (const file of files) {
|
|
5069
5272
|
const fnameLocale = file.match(FILE_RE)[1];
|
|
5070
|
-
if (fnameLocale !== void 0 && !
|
|
5273
|
+
if (fnameLocale !== void 0 && !LOCALE_RE6.test(fnameLocale)) continue;
|
|
5071
5274
|
let xml;
|
|
5072
5275
|
try {
|
|
5073
|
-
xml =
|
|
5276
|
+
xml = readFileSync16(join12(localeRoot, file), "utf8");
|
|
5074
5277
|
} catch (e) {
|
|
5075
5278
|
warnings.push(`angular-xliff: failed to read ${file}: ${e.message}`);
|
|
5076
5279
|
continue;
|
|
@@ -5115,9 +5318,9 @@ var angularXliff2 = {
|
|
|
5115
5318
|
};
|
|
5116
5319
|
|
|
5117
5320
|
// src/server/import/parsers/gettext-po.ts
|
|
5118
|
-
import { readdirSync as
|
|
5119
|
-
import { join as
|
|
5120
|
-
var
|
|
5321
|
+
import { readdirSync as readdirSync10, readFileSync as readFileSync17 } from "fs";
|
|
5322
|
+
import { join as join13 } from "path";
|
|
5323
|
+
var LOCALE_RE7 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/;
|
|
5121
5324
|
var DIRECTIVE_RE = /^(msgctxt|msgid_plural|msgid|msgstr)(?:\[(\d+)\])?[ \t]+"(.*)"\s*$/;
|
|
5122
5325
|
var CONT_RE = /^[ \t]*"(.*)"\s*$/;
|
|
5123
5326
|
function unescapePo(s) {
|
|
@@ -5204,21 +5407,21 @@ function parseEntries(text) {
|
|
|
5204
5407
|
}
|
|
5205
5408
|
function discoverPoFiles(root) {
|
|
5206
5409
|
const found = [];
|
|
5207
|
-
const entries =
|
|
5410
|
+
const entries = readdirSync10(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
5208
5411
|
for (const e of entries) {
|
|
5209
5412
|
if (e.isFile() && e.name.endsWith(".po")) {
|
|
5210
5413
|
const base = e.name.slice(0, -3);
|
|
5211
|
-
found.push({ path:
|
|
5212
|
-
} else if (e.isDirectory() &&
|
|
5213
|
-
for (const sub of [
|
|
5414
|
+
found.push({ path: join13(root, e.name), rel: e.name, locale: LOCALE_RE7.test(base) ? base : null });
|
|
5415
|
+
} else if (e.isDirectory() && LOCALE_RE7.test(e.name)) {
|
|
5416
|
+
for (const sub of [join13(e.name, "LC_MESSAGES"), e.name]) {
|
|
5214
5417
|
let names;
|
|
5215
5418
|
try {
|
|
5216
|
-
names =
|
|
5419
|
+
names = readdirSync10(join13(root, sub)).sort();
|
|
5217
5420
|
} catch {
|
|
5218
5421
|
continue;
|
|
5219
5422
|
}
|
|
5220
5423
|
for (const f of names) {
|
|
5221
|
-
if (f.endsWith(".po")) found.push({ path:
|
|
5424
|
+
if (f.endsWith(".po")) found.push({ path: join13(root, sub, f), rel: join13(sub, f), locale: e.name });
|
|
5222
5425
|
}
|
|
5223
5426
|
}
|
|
5224
5427
|
}
|
|
@@ -5234,7 +5437,7 @@ var gettextPo2 = {
|
|
|
5234
5437
|
for (const file of discoverPoFiles(localeRoot)) {
|
|
5235
5438
|
let entries;
|
|
5236
5439
|
try {
|
|
5237
|
-
entries = parseEntries(
|
|
5440
|
+
entries = parseEntries(readFileSync17(file.path, "utf8"));
|
|
5238
5441
|
} catch (e) {
|
|
5239
5442
|
warnings.push(`gettext-po: failed to parse ${file.rel}: ${e.message}`);
|
|
5240
5443
|
continue;
|
|
@@ -5279,9 +5482,9 @@ var gettextPo2 = {
|
|
|
5279
5482
|
};
|
|
5280
5483
|
|
|
5281
5484
|
// src/server/import/parsers/i18next-json.ts
|
|
5282
|
-
import { readdirSync as
|
|
5283
|
-
import { join as
|
|
5284
|
-
var
|
|
5485
|
+
import { readdirSync as readdirSync11, readFileSync as readFileSync18, statSync as statSync6 } from "fs";
|
|
5486
|
+
import { join as join14 } from "path";
|
|
5487
|
+
var LOCALE_RE8 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/;
|
|
5285
5488
|
var PLURAL_SUFFIX_RE = /^(.+)_(zero|one|two|few|many|other)$/;
|
|
5286
5489
|
var PLURAL_ARG = "count";
|
|
5287
5490
|
var DEFAULT_NAMESPACE = "translation";
|
|
@@ -5299,7 +5502,7 @@ function fromI18next(value) {
|
|
|
5299
5502
|
function ingestFile(path, label, prefix, locale, keys, warnings) {
|
|
5300
5503
|
let data;
|
|
5301
5504
|
try {
|
|
5302
|
-
data = JSON.parse(
|
|
5505
|
+
data = JSON.parse(readFileSync18(path, "utf8"));
|
|
5303
5506
|
} catch (e) {
|
|
5304
5507
|
warnings.push(`i18next-json: failed to parse ${label}: ${e.message}`);
|
|
5305
5508
|
return false;
|
|
@@ -5340,22 +5543,22 @@ var i18nextJson2 = {
|
|
|
5340
5543
|
const warnings = [];
|
|
5341
5544
|
const keys = {};
|
|
5342
5545
|
const locales = [];
|
|
5343
|
-
for (const entry of
|
|
5344
|
-
const full =
|
|
5546
|
+
for (const entry of readdirSync11(localeRoot).sort()) {
|
|
5547
|
+
const full = join14(localeRoot, entry);
|
|
5345
5548
|
if (safeIsDir2(full)) {
|
|
5346
|
-
if (!
|
|
5549
|
+
if (!LOCALE_RE8.test(entry)) continue;
|
|
5347
5550
|
if (opts?.locales && !opts.locales.includes(entry)) continue;
|
|
5348
5551
|
let any = false;
|
|
5349
|
-
for (const file of
|
|
5552
|
+
for (const file of readdirSync11(full).sort()) {
|
|
5350
5553
|
if (!file.endsWith(".json")) continue;
|
|
5351
5554
|
const ns = file.slice(0, -".json".length);
|
|
5352
5555
|
const prefix = ns === DEFAULT_NAMESPACE ? "" : `${ns}.`;
|
|
5353
|
-
if (ingestFile(
|
|
5556
|
+
if (ingestFile(join14(full, file), `${entry}/${file}`, prefix, entry, keys, warnings)) any = true;
|
|
5354
5557
|
}
|
|
5355
5558
|
if (any && !locales.includes(entry)) locales.push(entry);
|
|
5356
5559
|
} else if (entry.endsWith(".json")) {
|
|
5357
5560
|
const locale = entry.slice(0, -".json".length);
|
|
5358
|
-
if (!
|
|
5561
|
+
if (!LOCALE_RE8.test(locale)) continue;
|
|
5359
5562
|
if (opts?.locales && !opts.locales.includes(locale)) continue;
|
|
5360
5563
|
if (ingestFile(full, entry, "", locale, keys, warnings) && !locales.includes(locale)) {
|
|
5361
5564
|
locales.push(locale);
|
|
@@ -5367,9 +5570,9 @@ var i18nextJson2 = {
|
|
|
5367
5570
|
};
|
|
5368
5571
|
|
|
5369
5572
|
// src/server/import/parsers/rails-yaml.ts
|
|
5370
|
-
import { readdirSync as
|
|
5371
|
-
import { join as
|
|
5372
|
-
var
|
|
5573
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync19 } from "fs";
|
|
5574
|
+
import { join as join15 } from "path";
|
|
5575
|
+
var LOCALE_RE9 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/i;
|
|
5373
5576
|
var CATEGORY_SET = new Set(PLURAL_CATEGORIES);
|
|
5374
5577
|
function makeNode() {
|
|
5375
5578
|
return /* @__PURE__ */ Object.create(null);
|
|
@@ -5582,18 +5785,18 @@ var railsYaml2 = {
|
|
|
5582
5785
|
else flatten(v, key, locale, file);
|
|
5583
5786
|
}
|
|
5584
5787
|
};
|
|
5585
|
-
for (const file of
|
|
5788
|
+
for (const file of readdirSync12(localeRoot).sort()) {
|
|
5586
5789
|
if (!file.endsWith(".yml") && !file.endsWith(".yaml")) continue;
|
|
5587
5790
|
let text;
|
|
5588
5791
|
try {
|
|
5589
|
-
text =
|
|
5792
|
+
text = readFileSync19(join15(localeRoot, file), "utf8");
|
|
5590
5793
|
} catch (e) {
|
|
5591
5794
|
warnings.push(`rails-yaml: failed to read ${file}: ${e.message}`);
|
|
5592
5795
|
continue;
|
|
5593
5796
|
}
|
|
5594
5797
|
const { roots } = parseYamlSubset(text, file, warnings);
|
|
5595
5798
|
for (const token of Object.keys(roots).sort()) {
|
|
5596
|
-
if (!
|
|
5799
|
+
if (!LOCALE_RE9.test(token)) {
|
|
5597
5800
|
warnings.push(`rails-yaml: ${file}: top-level key "${token}" is not a locale; subtree skipped`);
|
|
5598
5801
|
continue;
|
|
5599
5802
|
}
|
|
@@ -5607,14 +5810,14 @@ var railsYaml2 = {
|
|
|
5607
5810
|
};
|
|
5608
5811
|
|
|
5609
5812
|
// src/server/import/parsers/apple-stringsdict.ts
|
|
5610
|
-
import { readdirSync as
|
|
5611
|
-
import { join as
|
|
5612
|
-
var
|
|
5813
|
+
import { readdirSync as readdirSync13, readFileSync as readFileSync20, statSync as statSync7 } from "fs";
|
|
5814
|
+
import { join as join16 } from "path";
|
|
5815
|
+
var LOCALE_RE10 = /^[a-z]{2,3}([_-][A-Za-z]{2,4}){0,2}$/;
|
|
5613
5816
|
var TABLE2 = "Localizable.stringsdict";
|
|
5614
5817
|
function localeFromLproj2(dir) {
|
|
5615
5818
|
const m = dir.match(/^(.+)\.lproj$/);
|
|
5616
5819
|
if (!m) return null;
|
|
5617
|
-
return
|
|
5820
|
+
return LOCALE_RE10.test(m[1]) ? m[1] : null;
|
|
5618
5821
|
}
|
|
5619
5822
|
function decodeEntities2(s) {
|
|
5620
5823
|
return s.replace(/&#x([0-9a-fA-F]+);/g, (_, h) => String.fromCodePoint(parseInt(h, 16))).replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(Number(d))).replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
@@ -5758,20 +5961,20 @@ var appleStringsdict2 = {
|
|
|
5758
5961
|
const warnings = [];
|
|
5759
5962
|
const keys = {};
|
|
5760
5963
|
const locales = [];
|
|
5761
|
-
for (const dir of
|
|
5964
|
+
for (const dir of readdirSync13(localeRoot).sort()) {
|
|
5762
5965
|
const locale = localeFromLproj2(dir);
|
|
5763
5966
|
if (!locale) continue;
|
|
5764
5967
|
if (opts?.locales && !opts.locales.includes(locale)) continue;
|
|
5765
|
-
const file =
|
|
5968
|
+
const file = join16(localeRoot, dir, TABLE2);
|
|
5766
5969
|
let text;
|
|
5767
5970
|
try {
|
|
5768
5971
|
if (!statSync7(file).isFile()) continue;
|
|
5769
|
-
text =
|
|
5972
|
+
text = readFileSync20(file, "utf8");
|
|
5770
5973
|
} catch {
|
|
5771
5974
|
continue;
|
|
5772
5975
|
}
|
|
5773
5976
|
locales.push(locale);
|
|
5774
|
-
const others =
|
|
5977
|
+
const others = readdirSync13(join16(localeRoot, dir)).filter(
|
|
5775
5978
|
(f) => f.endsWith(".stringsdict") && f !== TABLE2
|
|
5776
5979
|
);
|
|
5777
5980
|
if (others.length) {
|
|
@@ -5799,6 +6002,7 @@ var appleStringsdict2 = {
|
|
|
5799
6002
|
// src/server/import/parsers/index.ts
|
|
5800
6003
|
var REGISTRY = {
|
|
5801
6004
|
[vueI18nJson2.name]: vueI18nJson2,
|
|
6005
|
+
[nextIntlJson2.name]: nextIntlJson2,
|
|
5802
6006
|
[laravelPhp2.name]: laravelPhp2,
|
|
5803
6007
|
[flutterArb2.name]: flutterArb2,
|
|
5804
6008
|
[appleStrings2.name]: appleStrings2,
|
|
@@ -5818,6 +6022,9 @@ function getParser(name) {
|
|
|
5818
6022
|
var OUTPUT_BY_FORMAT = {
|
|
5819
6023
|
"laravel-php": { adapter: "laravel-php", path: "lang/{locale}/{namespace}.php" },
|
|
5820
6024
|
"vue-i18n-json": { adapter: "vue-i18n-json", path: "src/locale/{locale}.json" },
|
|
6025
|
+
// rootRelative: write back to wherever the messages dir was found (messages/,
|
|
6026
|
+
// src/messages/, …) rather than assuming the conventional root-level location.
|
|
6027
|
+
"next-intl-json": { adapter: "next-intl-json", path: "{locale}.json", rootRelative: true },
|
|
5821
6028
|
"flutter-arb": { adapter: "flutter-arb", path: "lib/l10n/app_{locale}.arb" },
|
|
5822
6029
|
"apple-strings": { adapter: "apple-strings", path: "{locale}.lproj/Localizable.strings", rootRelative: true },
|
|
5823
6030
|
// skipSourceLocale: ng extract-i18n owns messages.xlf (the source file); glotfile
|
|
@@ -6087,7 +6294,7 @@ function refreshLocationUsage(projectRoot, format) {
|
|
|
6087
6294
|
}
|
|
6088
6295
|
|
|
6089
6296
|
// src/server/export-run.ts
|
|
6090
|
-
import { existsSync as existsSync12, readFileSync as
|
|
6297
|
+
import { existsSync as existsSync12, readFileSync as readFileSync21, readdirSync as readdirSync14, rmdirSync, statSync as statSync8, unlinkSync } from "fs";
|
|
6091
6298
|
import { dirname as dirname2, resolve as resolve7, sep } from "path";
|
|
6092
6299
|
function effectiveLocales(config) {
|
|
6093
6300
|
const limit = config.exportLocales;
|
|
@@ -6143,7 +6350,7 @@ function pruneStaleLocaleFiles(output, validTokens, projectRoot) {
|
|
|
6143
6350
|
const re = segmentRegExp(segment);
|
|
6144
6351
|
let entries;
|
|
6145
6352
|
try {
|
|
6146
|
-
entries =
|
|
6353
|
+
entries = readdirSync14(dir, { withFileTypes: true });
|
|
6147
6354
|
} catch {
|
|
6148
6355
|
return;
|
|
6149
6356
|
}
|
|
@@ -6186,7 +6393,7 @@ function exportToDisk(state, projectRoot, opts) {
|
|
|
6186
6393
|
writtenPaths.add(abs);
|
|
6187
6394
|
let current = null;
|
|
6188
6395
|
try {
|
|
6189
|
-
current =
|
|
6396
|
+
current = readFileSync21(abs, "utf8");
|
|
6190
6397
|
} catch {
|
|
6191
6398
|
}
|
|
6192
6399
|
if (current === f.contents) {
|
|
@@ -6203,17 +6410,17 @@ function exportToDisk(state, projectRoot, opts) {
|
|
|
6203
6410
|
}
|
|
6204
6411
|
|
|
6205
6412
|
// src/server/ui-prefs.ts
|
|
6206
|
-
import { readFileSync as
|
|
6413
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
6207
6414
|
import { homedir } from "os";
|
|
6208
|
-
import { join as
|
|
6415
|
+
import { join as join17 } from "path";
|
|
6209
6416
|
var THEMES = ["system", "light", "dark"];
|
|
6210
6417
|
var isThemeMode = (v) => THEMES.includes(v);
|
|
6211
6418
|
var isPanelWidth = (v) => typeof v === "number" && Number.isFinite(v) && v >= 120 && v <= 1200;
|
|
6212
|
-
var defaultUiPrefsPath = () =>
|
|
6419
|
+
var defaultUiPrefsPath = () => join17(homedir(), ".glotfile", "ui.json");
|
|
6213
6420
|
var DEFAULTS = { theme: "system" };
|
|
6214
6421
|
function readJson(path) {
|
|
6215
6422
|
try {
|
|
6216
|
-
const parsed = JSON.parse(
|
|
6423
|
+
const parsed = JSON.parse(readFileSync22(path, "utf8"));
|
|
6217
6424
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
6218
6425
|
} catch {
|
|
6219
6426
|
return {};
|
|
@@ -6232,7 +6439,7 @@ function saveUiPrefs(path, prefs) {
|
|
|
6232
6439
|
}
|
|
6233
6440
|
|
|
6234
6441
|
// src/server/local-settings.ts
|
|
6235
|
-
import { readFileSync as
|
|
6442
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
6236
6443
|
import { resolve as resolve8 } from "path";
|
|
6237
6444
|
var EDITOR_IDS = ["vscode", "zed", "phpstorm"];
|
|
6238
6445
|
var isEditorId = (v) => EDITOR_IDS.includes(v);
|
|
@@ -6247,7 +6454,7 @@ var DEFAULT_EDITOR = "vscode";
|
|
|
6247
6454
|
var settingsPath = (projectRoot) => resolve8(projectRoot, ".glotfile", "settings.json");
|
|
6248
6455
|
function readJson2(path) {
|
|
6249
6456
|
try {
|
|
6250
|
-
const parsed = JSON.parse(
|
|
6457
|
+
const parsed = JSON.parse(readFileSync23(path, "utf8"));
|
|
6251
6458
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
6252
6459
|
} catch {
|
|
6253
6460
|
return {};
|
|
@@ -6336,8 +6543,8 @@ function createEventHub() {
|
|
|
6336
6543
|
}
|
|
6337
6544
|
|
|
6338
6545
|
// src/server/watch.ts
|
|
6339
|
-
import { statSync as statSync9, readdirSync as
|
|
6340
|
-
import { join as
|
|
6546
|
+
import { statSync as statSync9, readdirSync as readdirSync15 } from "fs";
|
|
6547
|
+
import { join as join18 } from "path";
|
|
6341
6548
|
import { createHash as createHash2 } from "crypto";
|
|
6342
6549
|
function hashState(state) {
|
|
6343
6550
|
return createHash2("sha1").update(serializeJson(state, state.config.format)).digest("hex");
|
|
@@ -6353,15 +6560,15 @@ function signature(statePath) {
|
|
|
6353
6560
|
const parts = [];
|
|
6354
6561
|
for (const rel of ["config.json", "keys.json"]) {
|
|
6355
6562
|
try {
|
|
6356
|
-
const s = statSync9(
|
|
6563
|
+
const s = statSync9(join18(dir, rel));
|
|
6357
6564
|
parts.push(`${rel}:${s.size}:${s.mtimeMs}`);
|
|
6358
6565
|
} catch {
|
|
6359
6566
|
}
|
|
6360
6567
|
}
|
|
6361
6568
|
try {
|
|
6362
|
-
for (const name of
|
|
6569
|
+
for (const name of readdirSync15(join18(dir, "locales")).sort()) {
|
|
6363
6570
|
if (!name.endsWith(".json")) continue;
|
|
6364
|
-
const s = statSync9(
|
|
6571
|
+
const s = statSync9(join18(dir, "locales", name));
|
|
6365
6572
|
parts.push(`${name}:${s.size}:${s.mtimeMs}`);
|
|
6366
6573
|
}
|
|
6367
6574
|
} catch {
|
|
@@ -6436,7 +6643,7 @@ function projectName(root) {
|
|
|
6436
6643
|
const nameFile = resolve9(root, ".idea", ".name");
|
|
6437
6644
|
if (existsSync13(nameFile)) {
|
|
6438
6645
|
try {
|
|
6439
|
-
const name =
|
|
6646
|
+
const name = readFileSync24(nameFile, "utf8").trim();
|
|
6440
6647
|
if (name) return name;
|
|
6441
6648
|
} catch {
|
|
6442
6649
|
}
|
|
@@ -6602,7 +6809,7 @@ function createApi(deps) {
|
|
|
6602
6809
|
if (depth > 4) return;
|
|
6603
6810
|
let entries = [];
|
|
6604
6811
|
try {
|
|
6605
|
-
entries =
|
|
6812
|
+
entries = readdirSync16(dir);
|
|
6606
6813
|
} catch {
|
|
6607
6814
|
return;
|
|
6608
6815
|
}
|
|
@@ -7622,7 +7829,7 @@ function createApi(deps) {
|
|
|
7622
7829
|
|
|
7623
7830
|
// src/server/server.ts
|
|
7624
7831
|
var here = dirname4(fileURLToPath(import.meta.url));
|
|
7625
|
-
var DEFAULT_UI_DIR =
|
|
7832
|
+
var DEFAULT_UI_DIR = join19(here, "..", "ui");
|
|
7626
7833
|
var MIME = {
|
|
7627
7834
|
".html": "text/html; charset=utf-8",
|
|
7628
7835
|
".js": "text/javascript; charset=utf-8",
|
|
@@ -7689,7 +7896,7 @@ function buildApp(opts) {
|
|
|
7689
7896
|
const file = await readFileResponse(target);
|
|
7690
7897
|
if (file) return file;
|
|
7691
7898
|
}
|
|
7692
|
-
const index = await readFileResponse(
|
|
7899
|
+
const index = await readFileResponse(join19(root, "index.html"));
|
|
7693
7900
|
if (index) return index;
|
|
7694
7901
|
return c.notFound();
|
|
7695
7902
|
});
|