lingo.dev 0.113.3 → 0.113.4
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/build/cli.cjs +535 -115
- package/build/cli.cjs.map +1 -1
- package/build/cli.mjs +427 -7
- package/build/cli.mjs.map +1 -1
- package/package.json +5 -5
package/build/cli.mjs
CHANGED
|
@@ -1874,9 +1874,9 @@ function createJsoncLoader() {
|
|
|
1874
1874
|
import { flatten, unflatten } from "flat";
|
|
1875
1875
|
import _6 from "lodash";
|
|
1876
1876
|
var OBJECT_NUMERIC_KEY_PREFIX = "__lingodotdev__obj__";
|
|
1877
|
-
function createFlatLoader() {
|
|
1877
|
+
function createFlatLoader(options) {
|
|
1878
1878
|
const composedLoader = composeLoaders(
|
|
1879
|
-
createDenormalizeLoader(),
|
|
1879
|
+
createDenormalizeLoader(options),
|
|
1880
1880
|
createNormalizeLoader()
|
|
1881
1881
|
);
|
|
1882
1882
|
return {
|
|
@@ -1889,16 +1889,29 @@ function createFlatLoader() {
|
|
|
1889
1889
|
}
|
|
1890
1890
|
};
|
|
1891
1891
|
}
|
|
1892
|
-
function createDenormalizeLoader() {
|
|
1892
|
+
function createDenormalizeLoader(options) {
|
|
1893
1893
|
return createLoader({
|
|
1894
1894
|
pull: async (locale, input2) => {
|
|
1895
1895
|
const inputDenormalized = denormalizeObjectKeys(input2 || {});
|
|
1896
|
-
const
|
|
1896
|
+
const preservedObjects = {};
|
|
1897
|
+
const nonPreservedInput = {};
|
|
1898
|
+
for (const [key, value] of Object.entries(inputDenormalized)) {
|
|
1899
|
+
if (options?.shouldPreserveObject?.(value)) {
|
|
1900
|
+
preservedObjects[key] = value;
|
|
1901
|
+
} else {
|
|
1902
|
+
nonPreservedInput[key] = value;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
const flattened = flatten(nonPreservedInput, {
|
|
1897
1906
|
delimiter: "/",
|
|
1898
1907
|
transformKey(key) {
|
|
1899
1908
|
return encodeURIComponent(String(key));
|
|
1900
1909
|
}
|
|
1901
1910
|
});
|
|
1911
|
+
const denormalized = {
|
|
1912
|
+
...flattened,
|
|
1913
|
+
...preservedObjects
|
|
1914
|
+
};
|
|
1902
1915
|
const keysMap = buildDenormalizedKeysMap(denormalized);
|
|
1903
1916
|
return { denormalized, keysMap };
|
|
1904
1917
|
},
|
|
@@ -2941,6 +2954,380 @@ function _removeLocale(input2, locale) {
|
|
|
2941
2954
|
return { ...input2, strings: newStrings };
|
|
2942
2955
|
}
|
|
2943
2956
|
|
|
2957
|
+
// src/cli/loaders/xcode-xcstrings-icu.ts
|
|
2958
|
+
var ICU_TYPE_MARKER = Symbol.for("@lingo.dev/icu-plural-object");
|
|
2959
|
+
var CLDR_PLURAL_CATEGORIES = /* @__PURE__ */ new Set([
|
|
2960
|
+
"zero",
|
|
2961
|
+
"one",
|
|
2962
|
+
"two",
|
|
2963
|
+
"few",
|
|
2964
|
+
"many",
|
|
2965
|
+
"other"
|
|
2966
|
+
]);
|
|
2967
|
+
function isICUPluralObject(value) {
|
|
2968
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2969
|
+
return false;
|
|
2970
|
+
}
|
|
2971
|
+
if (ICU_TYPE_MARKER in value) {
|
|
2972
|
+
return true;
|
|
2973
|
+
}
|
|
2974
|
+
if (!("icu" in value) || typeof value.icu !== "string") {
|
|
2975
|
+
return false;
|
|
2976
|
+
}
|
|
2977
|
+
const icuPluralPattern = /^\{[\w]+,\s*plural,\s*.+\}$/;
|
|
2978
|
+
if (!icuPluralPattern.test(value.icu)) {
|
|
2979
|
+
return false;
|
|
2980
|
+
}
|
|
2981
|
+
if (value._meta !== void 0) {
|
|
2982
|
+
if (typeof value._meta !== "object" || !value._meta.variables || typeof value._meta.variables !== "object") {
|
|
2983
|
+
return false;
|
|
2984
|
+
}
|
|
2985
|
+
for (const [varName, varMeta] of Object.entries(value._meta.variables)) {
|
|
2986
|
+
if (!varMeta || typeof varMeta !== "object" || typeof varMeta.format !== "string" || varMeta.role !== "plural" && varMeta.role !== "other") {
|
|
2987
|
+
return false;
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
return true;
|
|
2992
|
+
}
|
|
2993
|
+
function isPluralFormsObject(value) {
|
|
2994
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2995
|
+
return false;
|
|
2996
|
+
}
|
|
2997
|
+
const keys = Object.keys(value);
|
|
2998
|
+
if (keys.length === 0) {
|
|
2999
|
+
return false;
|
|
3000
|
+
}
|
|
3001
|
+
const allKeysAreCldr = keys.every((key) => CLDR_PLURAL_CATEGORIES.has(key));
|
|
3002
|
+
if (!allKeysAreCldr) {
|
|
3003
|
+
return false;
|
|
3004
|
+
}
|
|
3005
|
+
const allValuesAreStrings = keys.every(
|
|
3006
|
+
(key) => typeof value[key] === "string"
|
|
3007
|
+
);
|
|
3008
|
+
if (!allValuesAreStrings) {
|
|
3009
|
+
return false;
|
|
3010
|
+
}
|
|
3011
|
+
if (!("other" in value)) {
|
|
3012
|
+
return false;
|
|
3013
|
+
}
|
|
3014
|
+
return true;
|
|
3015
|
+
}
|
|
3016
|
+
function getRequiredPluralCategories(locale) {
|
|
3017
|
+
try {
|
|
3018
|
+
const pluralRules = new Intl.PluralRules(locale);
|
|
3019
|
+
const categories = pluralRules.resolvedOptions().pluralCategories;
|
|
3020
|
+
if (!categories || categories.length === 0) {
|
|
3021
|
+
throw new Error(`No plural categories found for locale: ${locale}`);
|
|
3022
|
+
}
|
|
3023
|
+
return categories;
|
|
3024
|
+
} catch (error) {
|
|
3025
|
+
console.warn(
|
|
3026
|
+
`[xcode-xcstrings-icu] Failed to resolve plural categories for locale "${locale}". Using fallback ["one", "other"]. Error: ${error instanceof Error ? error.message : String(error)}`
|
|
3027
|
+
);
|
|
3028
|
+
return ["one", "other"];
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
var CLDR_CATEGORY_TO_NUMBER = {
|
|
3032
|
+
zero: 0,
|
|
3033
|
+
one: 1,
|
|
3034
|
+
two: 2
|
|
3035
|
+
};
|
|
3036
|
+
var NUMBER_TO_CLDR_CATEGORY = {
|
|
3037
|
+
0: "zero",
|
|
3038
|
+
1: "one",
|
|
3039
|
+
2: "two"
|
|
3040
|
+
};
|
|
3041
|
+
function xcstringsToPluralWithMeta(pluralForms, sourceLocale = "en") {
|
|
3042
|
+
if (!pluralForms || Object.keys(pluralForms).length === 0) {
|
|
3043
|
+
throw new Error("pluralForms cannot be empty");
|
|
3044
|
+
}
|
|
3045
|
+
const requiredCategories = getRequiredPluralCategories(sourceLocale);
|
|
3046
|
+
const variables = {};
|
|
3047
|
+
const formatRegex = /(%(?:(\d+)\$)?(?:[+-])?(?:\d+)?(?:\.(\d+))?([lhqLzjt]*)([diuoxXfFeEgGaAcspn@]))/g;
|
|
3048
|
+
let maxMatches = [];
|
|
3049
|
+
let maxMatchText = "";
|
|
3050
|
+
for (const [form, text] of Object.entries(pluralForms)) {
|
|
3051
|
+
if (typeof text !== "string") {
|
|
3052
|
+
console.warn(
|
|
3053
|
+
`Warning: Plural form "${form}" has non-string value:`,
|
|
3054
|
+
text
|
|
3055
|
+
);
|
|
3056
|
+
continue;
|
|
3057
|
+
}
|
|
3058
|
+
const matches = [...text.matchAll(formatRegex)];
|
|
3059
|
+
if (matches.length > maxMatches.length) {
|
|
3060
|
+
maxMatches = matches;
|
|
3061
|
+
maxMatchText = text;
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
let lastNumericIndex = -1;
|
|
3065
|
+
maxMatches.forEach((match2, idx) => {
|
|
3066
|
+
const specifier = match2[5];
|
|
3067
|
+
if (/[diuoxXfFeE]/.test(specifier)) {
|
|
3068
|
+
lastNumericIndex = idx;
|
|
3069
|
+
}
|
|
3070
|
+
});
|
|
3071
|
+
let nonPluralCounter = 0;
|
|
3072
|
+
maxMatches.forEach((match2, idx) => {
|
|
3073
|
+
const fullFormat = match2[1];
|
|
3074
|
+
const position = match2[2];
|
|
3075
|
+
const precision = match2[3];
|
|
3076
|
+
const lengthMod = match2[4];
|
|
3077
|
+
const specifier = match2[5];
|
|
3078
|
+
const isPluralVar = idx === lastNumericIndex;
|
|
3079
|
+
const varName = isPluralVar ? "count" : `var${nonPluralCounter++}`;
|
|
3080
|
+
variables[varName] = {
|
|
3081
|
+
format: fullFormat,
|
|
3082
|
+
role: isPluralVar ? "plural" : "other"
|
|
3083
|
+
};
|
|
3084
|
+
});
|
|
3085
|
+
const variableKeys = Object.keys(variables);
|
|
3086
|
+
const icuForms = Object.entries(pluralForms).filter(([form, text]) => {
|
|
3087
|
+
if (typeof text !== "string") {
|
|
3088
|
+
return false;
|
|
3089
|
+
}
|
|
3090
|
+
return true;
|
|
3091
|
+
}).map(([form, text]) => {
|
|
3092
|
+
let processed = text;
|
|
3093
|
+
let vIdx = 0;
|
|
3094
|
+
processed = processed.replace(formatRegex, () => {
|
|
3095
|
+
if (vIdx >= variableKeys.length) {
|
|
3096
|
+
vIdx++;
|
|
3097
|
+
return "#";
|
|
3098
|
+
}
|
|
3099
|
+
const varName = variableKeys[vIdx];
|
|
3100
|
+
const varMeta = variables[varName];
|
|
3101
|
+
vIdx++;
|
|
3102
|
+
if (varMeta.role === "plural") {
|
|
3103
|
+
return "#";
|
|
3104
|
+
} else {
|
|
3105
|
+
return `{${varName}}`;
|
|
3106
|
+
}
|
|
3107
|
+
});
|
|
3108
|
+
const isRequired = requiredCategories.includes(form);
|
|
3109
|
+
const formKey = !isRequired && form in CLDR_CATEGORY_TO_NUMBER ? `=${CLDR_CATEGORY_TO_NUMBER[form]}` : form;
|
|
3110
|
+
return `${formKey} {${processed}}`;
|
|
3111
|
+
}).join(" ");
|
|
3112
|
+
const pluralVarName = Object.keys(variables).find((name) => variables[name].role === "plural") || "count";
|
|
3113
|
+
const icu = `{${pluralVarName}, plural, ${icuForms}}`;
|
|
3114
|
+
const result = {
|
|
3115
|
+
icu,
|
|
3116
|
+
_meta: Object.keys(variables).length > 0 ? { variables } : void 0,
|
|
3117
|
+
[ICU_TYPE_MARKER]: true
|
|
3118
|
+
// Add type marker for robust detection
|
|
3119
|
+
};
|
|
3120
|
+
return result;
|
|
3121
|
+
}
|
|
3122
|
+
function pluralWithMetaToXcstrings(data) {
|
|
3123
|
+
if (!data.icu) {
|
|
3124
|
+
throw new Error("ICU string is required");
|
|
3125
|
+
}
|
|
3126
|
+
const ast = parseICU(data.icu);
|
|
3127
|
+
if (!ast || ast.length === 0) {
|
|
3128
|
+
throw new Error("Invalid ICU format");
|
|
3129
|
+
}
|
|
3130
|
+
const pluralNode = ast.find((node) => node.type === "plural");
|
|
3131
|
+
if (!pluralNode) {
|
|
3132
|
+
throw new Error("No plural found in ICU format");
|
|
3133
|
+
}
|
|
3134
|
+
const forms = {};
|
|
3135
|
+
for (const [form, option] of Object.entries(pluralNode.options)) {
|
|
3136
|
+
let text = "";
|
|
3137
|
+
const optionValue = option.value;
|
|
3138
|
+
for (const element of optionValue) {
|
|
3139
|
+
if (element.type === "literal") {
|
|
3140
|
+
text += element.value;
|
|
3141
|
+
} else if (element.type === "pound") {
|
|
3142
|
+
const pluralVar = Object.entries(data._meta?.variables || {}).find(
|
|
3143
|
+
([_36, meta]) => meta.role === "plural"
|
|
3144
|
+
);
|
|
3145
|
+
text += pluralVar?.[1].format || "%lld";
|
|
3146
|
+
} else if (element.type === "argument") {
|
|
3147
|
+
const varName = element.value;
|
|
3148
|
+
const varMeta = data._meta?.variables?.[varName];
|
|
3149
|
+
text += varMeta?.format || "%@";
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
let xcstringsFormName = form;
|
|
3153
|
+
if (form.startsWith("=")) {
|
|
3154
|
+
const numValue = parseInt(form.substring(1), 10);
|
|
3155
|
+
xcstringsFormName = NUMBER_TO_CLDR_CATEGORY[numValue] || form;
|
|
3156
|
+
}
|
|
3157
|
+
forms[xcstringsFormName] = text;
|
|
3158
|
+
}
|
|
3159
|
+
return forms;
|
|
3160
|
+
}
|
|
3161
|
+
function parseICU(icu) {
|
|
3162
|
+
const match2 = icu.match(/\{(\w+),\s*plural,\s*(.+)\}$/);
|
|
3163
|
+
if (!match2) {
|
|
3164
|
+
throw new Error("Invalid ICU plural format");
|
|
3165
|
+
}
|
|
3166
|
+
const varName = match2[1];
|
|
3167
|
+
const formsText = match2[2];
|
|
3168
|
+
const options = {};
|
|
3169
|
+
let i = 0;
|
|
3170
|
+
while (i < formsText.length) {
|
|
3171
|
+
while (i < formsText.length && /\s/.test(formsText[i])) {
|
|
3172
|
+
i++;
|
|
3173
|
+
}
|
|
3174
|
+
if (i >= formsText.length) break;
|
|
3175
|
+
let formName = "";
|
|
3176
|
+
if (formsText[i] === "=") {
|
|
3177
|
+
formName += formsText[i];
|
|
3178
|
+
i++;
|
|
3179
|
+
while (i < formsText.length && /\d/.test(formsText[i])) {
|
|
3180
|
+
formName += formsText[i];
|
|
3181
|
+
i++;
|
|
3182
|
+
}
|
|
3183
|
+
} else {
|
|
3184
|
+
while (i < formsText.length && /\w/.test(formsText[i])) {
|
|
3185
|
+
formName += formsText[i];
|
|
3186
|
+
i++;
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
if (!formName) break;
|
|
3190
|
+
while (i < formsText.length && /\s/.test(formsText[i])) {
|
|
3191
|
+
i++;
|
|
3192
|
+
}
|
|
3193
|
+
if (i >= formsText.length || formsText[i] !== "{") {
|
|
3194
|
+
throw new Error(`Expected '{' after form name '${formName}'`);
|
|
3195
|
+
}
|
|
3196
|
+
i++;
|
|
3197
|
+
let braceCount = 1;
|
|
3198
|
+
let formText = "";
|
|
3199
|
+
while (i < formsText.length && braceCount > 0) {
|
|
3200
|
+
if (formsText[i] === "{") {
|
|
3201
|
+
braceCount++;
|
|
3202
|
+
formText += formsText[i];
|
|
3203
|
+
} else if (formsText[i] === "}") {
|
|
3204
|
+
braceCount--;
|
|
3205
|
+
if (braceCount > 0) {
|
|
3206
|
+
formText += formsText[i];
|
|
3207
|
+
}
|
|
3208
|
+
} else {
|
|
3209
|
+
formText += formsText[i];
|
|
3210
|
+
}
|
|
3211
|
+
i++;
|
|
3212
|
+
}
|
|
3213
|
+
if (braceCount !== 0) {
|
|
3214
|
+
const preview = formsText.substring(
|
|
3215
|
+
Math.max(0, i - 50),
|
|
3216
|
+
Math.min(formsText.length, i + 50)
|
|
3217
|
+
);
|
|
3218
|
+
throw new Error(
|
|
3219
|
+
`Unclosed brace for form '${formName}' in ICU MessageFormat.
|
|
3220
|
+
Expected ${braceCount} more closing brace(s).
|
|
3221
|
+
Context: ...${preview}...
|
|
3222
|
+
Full ICU: {${varName}, plural, ${formsText}}`
|
|
3223
|
+
);
|
|
3224
|
+
}
|
|
3225
|
+
const elements = parseFormText(formText);
|
|
3226
|
+
options[formName] = {
|
|
3227
|
+
value: elements
|
|
3228
|
+
};
|
|
3229
|
+
}
|
|
3230
|
+
return [
|
|
3231
|
+
{
|
|
3232
|
+
type: "plural",
|
|
3233
|
+
value: varName,
|
|
3234
|
+
options
|
|
3235
|
+
}
|
|
3236
|
+
];
|
|
3237
|
+
}
|
|
3238
|
+
function parseFormText(text) {
|
|
3239
|
+
const elements = [];
|
|
3240
|
+
let currentText = "";
|
|
3241
|
+
let i = 0;
|
|
3242
|
+
while (i < text.length) {
|
|
3243
|
+
if (text[i] === "#") {
|
|
3244
|
+
if (currentText) {
|
|
3245
|
+
elements.push({ type: "literal", value: currentText });
|
|
3246
|
+
currentText = "";
|
|
3247
|
+
}
|
|
3248
|
+
elements.push({ type: "pound" });
|
|
3249
|
+
i++;
|
|
3250
|
+
} else if (text[i] === "{") {
|
|
3251
|
+
if (currentText) {
|
|
3252
|
+
elements.push({ type: "literal", value: currentText });
|
|
3253
|
+
currentText = "";
|
|
3254
|
+
}
|
|
3255
|
+
let braceCount = 1;
|
|
3256
|
+
let j = i + 1;
|
|
3257
|
+
while (j < text.length && braceCount > 0) {
|
|
3258
|
+
if (text[j] === "{") {
|
|
3259
|
+
braceCount++;
|
|
3260
|
+
} else if (text[j] === "}") {
|
|
3261
|
+
braceCount--;
|
|
3262
|
+
}
|
|
3263
|
+
j++;
|
|
3264
|
+
}
|
|
3265
|
+
if (braceCount !== 0) {
|
|
3266
|
+
throw new Error("Unclosed variable reference");
|
|
3267
|
+
}
|
|
3268
|
+
const varName = text.slice(i + 1, j - 1);
|
|
3269
|
+
elements.push({ type: "argument", value: varName });
|
|
3270
|
+
i = j;
|
|
3271
|
+
} else {
|
|
3272
|
+
currentText += text[i];
|
|
3273
|
+
i++;
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
if (currentText) {
|
|
3277
|
+
elements.push({ type: "literal", value: currentText });
|
|
3278
|
+
}
|
|
3279
|
+
return elements;
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
// src/cli/loaders/xcode-xcstrings-v2-loader.ts
|
|
3283
|
+
function createXcodeXcstringsV2Loader(defaultLocale = "en") {
|
|
3284
|
+
return createLoader({
|
|
3285
|
+
async pull(locale, input2) {
|
|
3286
|
+
const result = {};
|
|
3287
|
+
for (const [key, value] of Object.entries(input2)) {
|
|
3288
|
+
if (isPluralFormsObject(value)) {
|
|
3289
|
+
try {
|
|
3290
|
+
result[key] = xcstringsToPluralWithMeta(value, locale);
|
|
3291
|
+
} catch (error) {
|
|
3292
|
+
console.error(
|
|
3293
|
+
`
|
|
3294
|
+
[xcode-xcstrings-icu] Failed to convert plural forms for key "${key}":`,
|
|
3295
|
+
`
|
|
3296
|
+
Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
3297
|
+
`
|
|
3298
|
+
Locale: ${locale}
|
|
3299
|
+
`
|
|
3300
|
+
);
|
|
3301
|
+
result[key] = value;
|
|
3302
|
+
}
|
|
3303
|
+
} else {
|
|
3304
|
+
result[key] = value;
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
return result;
|
|
3308
|
+
},
|
|
3309
|
+
async push(locale, payload) {
|
|
3310
|
+
const result = {};
|
|
3311
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
3312
|
+
if (isICUPluralObject(value)) {
|
|
3313
|
+
try {
|
|
3314
|
+
const pluralForms = pluralWithMetaToXcstrings(value);
|
|
3315
|
+
result[key] = pluralForms;
|
|
3316
|
+
} catch (error) {
|
|
3317
|
+
throw new Error(
|
|
3318
|
+
`Failed to write plural translation for key "${key}" (locale: ${locale}).
|
|
3319
|
+
${error instanceof Error ? error.message : String(error)}`
|
|
3320
|
+
);
|
|
3321
|
+
}
|
|
3322
|
+
} else {
|
|
3323
|
+
result[key] = value;
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
return result;
|
|
3327
|
+
}
|
|
3328
|
+
});
|
|
3329
|
+
}
|
|
3330
|
+
|
|
2944
3331
|
// src/cli/loaders/unlocalizable.ts
|
|
2945
3332
|
import _10 from "lodash";
|
|
2946
3333
|
import _isUrl from "is-url";
|
|
@@ -4544,6 +4931,15 @@ function variableExtractLoader(params) {
|
|
|
4544
4931
|
const inputValues = _16.omitBy(input2, _16.isEmpty);
|
|
4545
4932
|
for (const [key, value] of Object.entries(inputValues)) {
|
|
4546
4933
|
const originalValue = originalInput[key];
|
|
4934
|
+
if (isICUPluralObject(originalValue)) {
|
|
4935
|
+
const icuValue = isICUPluralObject(value) ? { icu: value.icu } : value;
|
|
4936
|
+
result[key] = {
|
|
4937
|
+
value: icuValue,
|
|
4938
|
+
variables: []
|
|
4939
|
+
// Metadata stored separately, not in variables
|
|
4940
|
+
};
|
|
4941
|
+
continue;
|
|
4942
|
+
}
|
|
4547
4943
|
const matches = originalValue.match(specifierPattern) || [];
|
|
4548
4944
|
result[key] = result[key] || {
|
|
4549
4945
|
value,
|
|
@@ -4563,11 +4959,21 @@ function variableExtractLoader(params) {
|
|
|
4563
4959
|
const result = {};
|
|
4564
4960
|
for (const [key, valueObj] of Object.entries(data)) {
|
|
4565
4961
|
result[key] = valueObj.value;
|
|
4962
|
+
const resultValue = result[key];
|
|
4963
|
+
if (isICUPluralObject(resultValue)) {
|
|
4964
|
+
const originalValue = originalInput?.[key];
|
|
4965
|
+
if (isICUPluralObject(originalValue) && originalValue._meta) {
|
|
4966
|
+
resultValue._meta = originalValue._meta;
|
|
4967
|
+
resultValue[Symbol.for("@lingo.dev/icu-plural-object")] = true;
|
|
4968
|
+
}
|
|
4969
|
+
}
|
|
4566
4970
|
for (let i = 0; i < valueObj.variables.length; i++) {
|
|
4567
4971
|
const variable = valueObj.variables[i];
|
|
4568
4972
|
const currentValue = result[key];
|
|
4569
|
-
|
|
4570
|
-
|
|
4973
|
+
if (typeof currentValue === "string") {
|
|
4974
|
+
const newValue = currentValue?.replace(`{variable:${i}}`, variable);
|
|
4975
|
+
result[key] = newValue;
|
|
4976
|
+
}
|
|
4571
4977
|
}
|
|
4572
4978
|
}
|
|
4573
4979
|
return result;
|
|
@@ -7358,6 +7764,20 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
|
|
|
7358
7764
|
createVariableLoader({ type: "ieee" }),
|
|
7359
7765
|
createUnlocalizableLoader(options.returnUnlocalizedKeys)
|
|
7360
7766
|
);
|
|
7767
|
+
case "xcode-xcstrings-v2":
|
|
7768
|
+
return composeLoaders(
|
|
7769
|
+
createTextFileLoader(bucketPathPattern),
|
|
7770
|
+
createPlutilJsonTextLoader(),
|
|
7771
|
+
createJsonLoader(),
|
|
7772
|
+
createXcodeXcstringsLoader(options.defaultLocale),
|
|
7773
|
+
createXcodeXcstringsV2Loader(options.defaultLocale),
|
|
7774
|
+
createFlatLoader({ shouldPreserveObject: isICUPluralObject }),
|
|
7775
|
+
createEnsureKeyOrderLoader(),
|
|
7776
|
+
createLockedKeysLoader(lockedKeys || []),
|
|
7777
|
+
createSyncLoader(),
|
|
7778
|
+
createVariableLoader({ type: "ieee" }),
|
|
7779
|
+
createUnlocalizableLoader(options.returnUnlocalizedKeys)
|
|
7780
|
+
);
|
|
7361
7781
|
case "yaml":
|
|
7362
7782
|
return composeLoaders(
|
|
7363
7783
|
createTextFileLoader(bucketPathPattern),
|
|
@@ -11783,7 +12203,7 @@ async function renderHero2() {
|
|
|
11783
12203
|
// package.json
|
|
11784
12204
|
var package_default = {
|
|
11785
12205
|
name: "lingo.dev",
|
|
11786
|
-
version: "0.113.
|
|
12206
|
+
version: "0.113.4",
|
|
11787
12207
|
description: "Lingo.dev CLI",
|
|
11788
12208
|
private: false,
|
|
11789
12209
|
publishConfig: {
|