locon 1.4.6 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +496 -36
- package/dist/index.d.ts +187 -10
- package/dist/index.js +510 -75
- package/package.json +27 -10
- package/skills/locon-sync/SKILL.md +158 -0
- package/skills/locon-sync/agents/openai.yaml +4 -0
- package/skills/locon-sync/scripts/check-locon-assets.mjs +594 -0
- package/skills/locon-sync/scripts/write_locale.py +229 -0
- package/dist/components/LText.d.mts +0 -10
- package/dist/components/LText.d.ts +0 -10
- package/dist/components/LText.js +0 -41
- package/dist/components/LText.mjs +0 -11
- package/dist/hooks/useLocon.d.mts +0 -6
- package/dist/hooks/useLocon.d.ts +0 -6
- package/dist/hooks/useLocon.js +0 -30
- package/dist/hooks/useLocon.mjs +0 -10
- package/dist/index.d.mts +0 -19
- package/dist/index.mjs +0 -104
- package/dist/types/Assets.d.mts +0 -3
- package/dist/types/Assets.d.ts +0 -3
- package/dist/types/Assets.js +0 -16
- package/dist/types/Assets.mjs +0 -0
- package/dist/types/LoconContext.d.mts +0 -12
- package/dist/types/LoconContext.d.ts +0 -12
- package/dist/types/LoconContext.js +0 -16
- package/dist/types/LoconContext.mjs +0 -0
- package/dist/utils/getSystemLanguage.d.mts +0 -7
- package/dist/utils/getSystemLanguage.d.ts +0 -7
- package/dist/utils/getSystemLanguage.js +0 -125
- package/dist/utils/getSystemLanguage.mjs +0 -105
package/dist/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,38 +15,468 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
|
|
20
|
+
// src/locon/index.tsx
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
LText: () => LText_default,
|
|
32
24
|
LoconContext: () => LoconContext,
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
RTL_LANGUAGES: () => RTL_LANGUAGES,
|
|
26
|
+
RTL_SCRIPTS: () => RTL_SCRIPTS,
|
|
27
|
+
applyRTL: () => applyRTL,
|
|
28
|
+
createTranslator: () => createTranslator_default,
|
|
29
|
+
default: () => index_default,
|
|
30
|
+
getSystemLanguage: () => getSystemLanguage_default,
|
|
31
|
+
intlLocale: () => intlLocale_default,
|
|
32
|
+
isRtlLocale: () => isRtlLocale,
|
|
33
|
+
resolveLocale: () => resolveLocale_default,
|
|
34
|
+
useLocon: () => useLocon_default
|
|
35
35
|
});
|
|
36
|
-
module.exports = __toCommonJS(
|
|
37
|
-
var
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
var import_react2 = require("react");
|
|
38
|
+
|
|
39
|
+
// src/locon/utils/createTranslator.ts
|
|
40
|
+
var reverseIndexCache = /* @__PURE__ */ new WeakMap();
|
|
41
|
+
function getReverseIndex(assets, locale) {
|
|
42
|
+
let perLocale = reverseIndexCache.get(assets);
|
|
43
|
+
if (!perLocale) {
|
|
44
|
+
perLocale = /* @__PURE__ */ new Map();
|
|
45
|
+
reverseIndexCache.set(assets, perLocale);
|
|
46
|
+
}
|
|
47
|
+
const cached = perLocale.get(locale);
|
|
48
|
+
if (cached) {
|
|
49
|
+
return cached;
|
|
50
|
+
}
|
|
51
|
+
const index = /* @__PURE__ */ new Map();
|
|
52
|
+
const localeAssets = assets[locale];
|
|
53
|
+
if (localeAssets) {
|
|
54
|
+
for (const key of Object.keys(localeAssets)) {
|
|
55
|
+
const value = localeAssets[key];
|
|
56
|
+
if (value !== void 0 && !index.has(value)) {
|
|
57
|
+
index.set(value, key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
perLocale.set(locale, index);
|
|
62
|
+
return index;
|
|
63
|
+
}
|
|
64
|
+
function interpolate(value, params) {
|
|
65
|
+
if (!params) {
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
return value.replace(
|
|
69
|
+
/\{(\w+)\}/g,
|
|
70
|
+
(match, token) => params[token] === void 0 ? match : String(params[token])
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
var PLURAL_SUFFIX = /_(zero|one|two|few|many|other)$/;
|
|
74
|
+
function pluralCategory(count, locale) {
|
|
75
|
+
try {
|
|
76
|
+
return new Intl.PluralRules(locale.replace(/_/g, "-")).select(count);
|
|
77
|
+
} catch {
|
|
78
|
+
return count === 1 ? "one" : "other";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function createTranslator({ assets, locale, defaultLocale = "en", projectLocale }) {
|
|
82
|
+
const resolvedProjectLocale = projectLocale || defaultLocale;
|
|
83
|
+
const read = (fromLocale, key) => {
|
|
84
|
+
const value = assets[fromLocale]?.[key];
|
|
85
|
+
return value === void 0 || value === "" ? void 0 : value;
|
|
86
|
+
};
|
|
87
|
+
const keyFor = (input, targetLocale) => {
|
|
88
|
+
if (assets[targetLocale]?.[input] !== void 0 || assets[defaultLocale]?.[input] !== void 0 || assets[resolvedProjectLocale]?.[input] !== void 0) {
|
|
89
|
+
return input;
|
|
90
|
+
}
|
|
91
|
+
return getReverseIndex(assets, resolvedProjectLocale).get(input) ?? getReverseIndex(assets, defaultLocale).get(input) ?? input;
|
|
92
|
+
};
|
|
93
|
+
return function l(assetKey, options) {
|
|
94
|
+
if (!assetKey) {
|
|
95
|
+
return "";
|
|
96
|
+
}
|
|
97
|
+
const targetLocale = options?.locale || locale;
|
|
98
|
+
const resolvedKey = keyFor(assetKey, targetLocale);
|
|
99
|
+
const key = options?.count === void 0 ? resolvedKey : resolvedKey.replace(PLURAL_SUFFIX, "");
|
|
100
|
+
const params = options?.count === void 0 ? options?.params : { ...options.params, count: options.count };
|
|
101
|
+
for (const candidateLocale of [targetLocale, defaultLocale, resolvedProjectLocale]) {
|
|
102
|
+
const candidateKeys = options?.count === void 0 ? [key] : [`${key}_${pluralCategory(options.count, candidateLocale)}`, `${key}_other`, key];
|
|
103
|
+
for (const candidateKey of candidateKeys) {
|
|
104
|
+
const value = read(candidateLocale, candidateKey);
|
|
105
|
+
if (value !== void 0) {
|
|
106
|
+
return interpolate(value, params);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return interpolate(options?.fallback ?? assetKey, params);
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
var createTranslator_default = createTranslator;
|
|
114
|
+
|
|
115
|
+
// src/locon/utils/getSystemLanguage.ts
|
|
116
|
+
function isModuleNotFound(error) {
|
|
117
|
+
const candidate = error;
|
|
118
|
+
if (candidate?.code === "MODULE_NOT_FOUND") {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return /cannot find module|requiring unknown module|could not be found|unable to resolve/i.test(
|
|
122
|
+
candidate?.message ?? ""
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
function matchLocale(deviceTags, availableLocales) {
|
|
126
|
+
const parse = (locale) => {
|
|
127
|
+
const normalized = locale.toLowerCase().replace(/_/g, "-");
|
|
128
|
+
const subtags = normalized.split("-");
|
|
129
|
+
const extensionIndex = subtags.findIndex((subtag, index) => index > 0 && subtag.length === 1);
|
|
130
|
+
const coreSubtags = subtags.slice(1, extensionIndex < 0 ? void 0 : extensionIndex);
|
|
131
|
+
const explicitScript = coreSubtags.find((subtag) => /^[a-z]{4}$/.test(subtag));
|
|
132
|
+
const region = coreSubtags.find((subtag) => /^[a-z]{2}$|^\d{3}$/.test(subtag));
|
|
133
|
+
const chineseRegionScript = subtags[0] === "zh" && region ? ["tw", "hk", "mo"].includes(region) ? "hant" : ["cn", "sg", "my"].includes(region) ? "hans" : void 0 : void 0;
|
|
134
|
+
let script = explicitScript ?? chineseRegionScript;
|
|
135
|
+
if (!script) {
|
|
136
|
+
try {
|
|
137
|
+
script = new Intl.Locale(normalized).maximize().script?.toLowerCase();
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
normalized,
|
|
143
|
+
language: subtags[0],
|
|
144
|
+
// Script is normally the second subtag. Looking until the first
|
|
145
|
+
// extension also handles legacy extlang-shaped tags without confusing a
|
|
146
|
+
// four-character variant beginning with a digit for a script. Likely
|
|
147
|
+
// subtags distinguish region-only tags such as zh-TW and zh-CN.
|
|
148
|
+
explicitScript,
|
|
149
|
+
script
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
const available = availableLocales.map((locale) => ({ locale, ...parse(locale) }));
|
|
153
|
+
for (const tag of deviceTags) {
|
|
154
|
+
if (!tag) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const requested = parse(tag);
|
|
158
|
+
const exact = available.find((entry) => entry.normalized === requested.normalized);
|
|
159
|
+
if (exact) {
|
|
160
|
+
return exact.locale;
|
|
161
|
+
}
|
|
162
|
+
const languageEntries = available.filter((entry) => entry.language === requested.language);
|
|
163
|
+
const availableScripts = new Set(languageEntries.map((entry) => entry.script).filter(Boolean));
|
|
164
|
+
const scriptMatters = Boolean(requested.explicitScript || availableScripts.size > 1);
|
|
165
|
+
const sameScript = scriptMatters && requested.script ? available.find((entry) => entry.language === requested.language && entry.script === requested.script) : void 0;
|
|
166
|
+
if (sameScript) {
|
|
167
|
+
return sameScript.locale;
|
|
168
|
+
}
|
|
169
|
+
const language = available.find((entry) => entry.normalized === requested.language);
|
|
170
|
+
if (language) {
|
|
171
|
+
return language.locale;
|
|
172
|
+
}
|
|
173
|
+
const sameLanguage = available.find((entry) => entry.language === requested.language);
|
|
174
|
+
if (sameLanguage) {
|
|
175
|
+
return sameLanguage.locale;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
function tagsFromReactNativeLocalize() {
|
|
181
|
+
try {
|
|
182
|
+
const RNLocalize = require("react-native-localize");
|
|
183
|
+
if (typeof RNLocalize?.getLocales === "function") {
|
|
184
|
+
return RNLocalize.getLocales().flatMap(
|
|
185
|
+
(locale) => [locale.languageTag, locale.languageCode].filter(Boolean)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
if (!isModuleNotFound(error)) {
|
|
190
|
+
console.warn("[locon] react-native-localize failed:", error);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
function tagsFromExpoLocalization() {
|
|
196
|
+
try {
|
|
197
|
+
const Localization = require("expo-localization");
|
|
198
|
+
if (typeof Localization?.getLocales === "function") {
|
|
199
|
+
return Localization.getLocales().flatMap(
|
|
200
|
+
(locale) => [locale.languageTag, locale.languageCode].filter(Boolean)
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (!isModuleNotFound(error)) {
|
|
205
|
+
console.warn("[locon] expo-localization failed:", error);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
function tagsFromNativeModules() {
|
|
211
|
+
try {
|
|
212
|
+
const { NativeModules, Platform } = require("react-native");
|
|
213
|
+
const tags = [];
|
|
214
|
+
if (Platform?.OS === "ios") {
|
|
215
|
+
const appleLanguages = NativeModules?.SettingsManager?.settings?.AppleLanguages;
|
|
216
|
+
if (Array.isArray(appleLanguages)) {
|
|
217
|
+
tags.push(...appleLanguages);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const localeIdentifier = NativeModules?.I18nManager?.localeIdentifier;
|
|
221
|
+
if (typeof localeIdentifier === "string") {
|
|
222
|
+
tags.push(localeIdentifier);
|
|
223
|
+
}
|
|
224
|
+
return tags;
|
|
225
|
+
} catch {
|
|
226
|
+
return [];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function tagsFromIntl() {
|
|
230
|
+
try {
|
|
231
|
+
const systemLocale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
232
|
+
return systemLocale ? [systemLocale] : [];
|
|
233
|
+
} catch {
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function getSystemLanguage(availableLocales) {
|
|
238
|
+
if (!availableLocales?.length) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
const sources = [tagsFromExpoLocalization, tagsFromReactNativeLocalize, tagsFromNativeModules, tagsFromIntl];
|
|
242
|
+
for (const source of sources) {
|
|
243
|
+
const match = matchLocale(source(), availableLocales);
|
|
244
|
+
if (match) {
|
|
245
|
+
return match;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
var getSystemLanguage_default = getSystemLanguage;
|
|
251
|
+
|
|
252
|
+
// src/locon/utils/resolveLocale.ts
|
|
253
|
+
function resolveLocale({
|
|
254
|
+
assets,
|
|
255
|
+
currentLocale,
|
|
256
|
+
defaultLocale = "en",
|
|
257
|
+
autodetect = true,
|
|
258
|
+
systemLocale
|
|
259
|
+
}) {
|
|
260
|
+
if (currentLocale) {
|
|
261
|
+
return currentLocale;
|
|
262
|
+
}
|
|
263
|
+
if (!autodetect) {
|
|
264
|
+
return defaultLocale;
|
|
265
|
+
}
|
|
266
|
+
const detected = systemLocale === void 0 ? getSystemLanguage_default(Object.keys(assets)) : systemLocale;
|
|
267
|
+
return detected ?? defaultLocale;
|
|
268
|
+
}
|
|
269
|
+
var resolveLocale_default = resolveLocale;
|
|
270
|
+
|
|
271
|
+
// src/locon/utils/rtl.ts
|
|
272
|
+
var RTL_LANGUAGES = /* @__PURE__ */ new Set([
|
|
273
|
+
"ar",
|
|
274
|
+
// Arabic
|
|
275
|
+
"arc",
|
|
276
|
+
// Aramaic
|
|
277
|
+
"ckb",
|
|
278
|
+
// Central Kurdish (Sorani)
|
|
279
|
+
"dv",
|
|
280
|
+
// Divehi
|
|
281
|
+
"fa",
|
|
282
|
+
// Persian
|
|
283
|
+
"glk",
|
|
284
|
+
// Gilaki
|
|
285
|
+
"he",
|
|
286
|
+
// Hebrew
|
|
287
|
+
"khw",
|
|
288
|
+
// Khowar
|
|
289
|
+
"ks",
|
|
290
|
+
// Kashmiri (Perso-Arabic)
|
|
291
|
+
"lrc",
|
|
292
|
+
// Northern Luri
|
|
293
|
+
"mzn",
|
|
294
|
+
// Mazanderani
|
|
295
|
+
"nqo",
|
|
296
|
+
// N'Ko
|
|
297
|
+
"pnb",
|
|
298
|
+
// Western Punjabi
|
|
299
|
+
"ps",
|
|
300
|
+
// Pashto
|
|
301
|
+
"sd",
|
|
302
|
+
// Sindhi (Perso-Arabic)
|
|
303
|
+
"syr",
|
|
304
|
+
// Syriac
|
|
305
|
+
"ug",
|
|
306
|
+
// Uyghur
|
|
307
|
+
"ur",
|
|
308
|
+
// Urdu
|
|
309
|
+
"yi"
|
|
310
|
+
// Yiddish
|
|
311
|
+
]);
|
|
312
|
+
var RTL_SCRIPTS = /* @__PURE__ */ new Set([
|
|
313
|
+
"adlm",
|
|
314
|
+
"arab",
|
|
315
|
+
"aran",
|
|
316
|
+
"armi",
|
|
317
|
+
"avst",
|
|
318
|
+
"chrs",
|
|
319
|
+
"cprt",
|
|
320
|
+
"elym",
|
|
321
|
+
"hatr",
|
|
322
|
+
"hebr",
|
|
323
|
+
"hung",
|
|
324
|
+
"khar",
|
|
325
|
+
"lydi",
|
|
326
|
+
"mand",
|
|
327
|
+
"mani",
|
|
328
|
+
"mend",
|
|
329
|
+
"merc",
|
|
330
|
+
"mero",
|
|
331
|
+
"narb",
|
|
332
|
+
"nbat",
|
|
333
|
+
"nkoo",
|
|
334
|
+
"orkh",
|
|
335
|
+
"ougr",
|
|
336
|
+
"palm",
|
|
337
|
+
"phli",
|
|
338
|
+
"phlp",
|
|
339
|
+
"phnx",
|
|
340
|
+
"prti",
|
|
341
|
+
"rohg",
|
|
342
|
+
"samr",
|
|
343
|
+
"sarb",
|
|
344
|
+
"sogd",
|
|
345
|
+
"sogo",
|
|
346
|
+
"syrc",
|
|
347
|
+
"thaa",
|
|
348
|
+
"yezi"
|
|
349
|
+
]);
|
|
350
|
+
var lastRequestedRTL;
|
|
351
|
+
function rtlFromIntl(locale) {
|
|
352
|
+
try {
|
|
353
|
+
const likelyLocale = new Intl.Locale(locale.replace(/_/g, "-")).maximize();
|
|
354
|
+
const localeWithDirection = likelyLocale;
|
|
355
|
+
const direction = localeWithDirection.getTextInfo?.().direction ?? localeWithDirection.textInfo?.direction;
|
|
356
|
+
if (direction === "rtl") {
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
if (direction === "ltr") {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
const likelyScript = likelyLocale.script?.toLowerCase();
|
|
363
|
+
return likelyScript && RTL_SCRIPTS.has(likelyScript) ? true : void 0;
|
|
364
|
+
} catch {
|
|
365
|
+
return void 0;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
function isRtlLocale(locale) {
|
|
369
|
+
if (!locale) {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
const subtags = locale.split(/[-_]/);
|
|
373
|
+
const languageCode = subtags[0]?.toLowerCase();
|
|
374
|
+
const extensionIndex = subtags.findIndex((subtag, index) => index > 0 && subtag.length === 1);
|
|
375
|
+
const coreSubtags = subtags.slice(1, extensionIndex < 0 ? void 0 : extensionIndex);
|
|
376
|
+
const scriptCode = coreSubtags.find((subtag) => /^[a-z]{4}$/i.test(subtag))?.toLowerCase();
|
|
377
|
+
if (scriptCode) {
|
|
378
|
+
return RTL_SCRIPTS.has(scriptCode) || rtlFromIntl(locale) === true;
|
|
379
|
+
}
|
|
380
|
+
const runtimeDirection = rtlFromIntl(locale);
|
|
381
|
+
if (runtimeDirection !== void 0) {
|
|
382
|
+
return runtimeDirection;
|
|
383
|
+
}
|
|
384
|
+
return Boolean(languageCode && RTL_LANGUAGES.has(languageCode));
|
|
385
|
+
}
|
|
386
|
+
function applyRTL(locale) {
|
|
387
|
+
const shouldBeRTL = isRtlLocale(locale);
|
|
388
|
+
try {
|
|
389
|
+
const { I18nManager } = require("react-native");
|
|
390
|
+
if (!I18nManager || typeof I18nManager.forceRTL !== "function") {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
I18nManager.allowRTL?.(true);
|
|
394
|
+
const renderedRTL = Boolean(I18nManager.isRTL);
|
|
395
|
+
const effectiveRequestedRTL = lastRequestedRTL ?? renderedRTL;
|
|
396
|
+
if (effectiveRequestedRTL !== shouldBeRTL) {
|
|
397
|
+
I18nManager.forceRTL(shouldBeRTL);
|
|
398
|
+
}
|
|
399
|
+
lastRequestedRTL = shouldBeRTL;
|
|
400
|
+
return renderedRTL !== shouldBeRTL;
|
|
401
|
+
} catch {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/locon/components/LText.tsx
|
|
407
|
+
var import_react_native = require("react-native");
|
|
408
|
+
|
|
409
|
+
// src/locon/hooks/useLocon.ts
|
|
38
410
|
var import_react = require("react");
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
411
|
+
function useLocon() {
|
|
412
|
+
const locon = (0, import_react.useContext)(LoconContext);
|
|
413
|
+
return locon;
|
|
414
|
+
}
|
|
415
|
+
var useLocon_default = useLocon;
|
|
416
|
+
|
|
417
|
+
// src/locon/components/LText.tsx
|
|
418
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
419
|
+
function LText({ children, assetKey, params, count, locale, ...props }) {
|
|
420
|
+
const { l } = useLocon_default();
|
|
421
|
+
const value = l(assetKey || children, { params, count, locale, fallback: assetKey ? children : void 0 });
|
|
422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { ...props, children: value });
|
|
423
|
+
}
|
|
424
|
+
var LText_default = LText;
|
|
425
|
+
|
|
426
|
+
// src/locon/utils/intlLocale.ts
|
|
427
|
+
function intlLocale(locale, extensions = {}) {
|
|
428
|
+
const normalizedLocale = locale.replace(/_/g, "-");
|
|
429
|
+
const requested = [];
|
|
430
|
+
if (extensions.calendar) {
|
|
431
|
+
requested.push(["ca", extensions.calendar]);
|
|
432
|
+
}
|
|
433
|
+
if (extensions.numbering) {
|
|
434
|
+
requested.push(["nu", extensions.numbering]);
|
|
435
|
+
}
|
|
436
|
+
if (!requested.length) {
|
|
437
|
+
return normalizedLocale;
|
|
438
|
+
}
|
|
439
|
+
const subtags = normalizedLocale.split("-");
|
|
440
|
+
const isSingleton = (subtag) => subtag.length === 1;
|
|
441
|
+
const privateUseIndex = subtags.findIndex((subtag, index) => index > 0 && subtag.toLowerCase() === "x");
|
|
442
|
+
const unicodeIndex = subtags.findIndex(
|
|
443
|
+
(subtag, index) => index > 0 && (privateUseIndex < 0 || index < privateUseIndex) && subtag.toLowerCase() === "u"
|
|
444
|
+
);
|
|
445
|
+
if (unicodeIndex >= 0) {
|
|
446
|
+
const nextSingleton = subtags.findIndex((subtag, index) => index > unicodeIndex && isSingleton(subtag));
|
|
447
|
+
const unicodeEnd = nextSingleton < 0 ? subtags.length : nextSingleton;
|
|
448
|
+
const existingKeys = new Set(
|
|
449
|
+
subtags.slice(unicodeIndex + 1, unicodeEnd).filter((subtag) => subtag.length === 2).map((subtag) => subtag.toLowerCase())
|
|
450
|
+
);
|
|
451
|
+
const additions = requested.flatMap(([key, value]) => existingKeys.has(key) ? [] : [key, value]);
|
|
452
|
+
if (!additions.length) {
|
|
453
|
+
return normalizedLocale;
|
|
454
|
+
}
|
|
455
|
+
subtags.splice(unicodeEnd, 0, ...additions);
|
|
456
|
+
return subtags.join("-");
|
|
457
|
+
}
|
|
458
|
+
const insertionIndex = privateUseIndex < 0 ? subtags.length : privateUseIndex;
|
|
459
|
+
subtags.splice(insertionIndex, 0, "u", ...requested.flat());
|
|
460
|
+
return subtags.join("-");
|
|
461
|
+
}
|
|
462
|
+
var intlLocale_default = intlLocale;
|
|
463
|
+
|
|
464
|
+
// src/locon/index.tsx
|
|
465
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
466
|
+
var fallbackTranslator = createTranslator_default({ assets: {}, locale: "en" });
|
|
467
|
+
var LoconContext = (0, import_react2.createContext)({
|
|
43
468
|
assets: {},
|
|
469
|
+
locales: [],
|
|
44
470
|
currentLocale: "en",
|
|
45
471
|
defaultLocale: "en",
|
|
472
|
+
projectLocale: "en",
|
|
473
|
+
systemLocale: null,
|
|
474
|
+
isRTL: false,
|
|
46
475
|
autodetect: true,
|
|
47
476
|
setLocale: () => {
|
|
48
477
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Default implementation
|
|
478
|
+
l: fallbackTranslator,
|
|
479
|
+
lIn: (locale, assetKey, options) => fallbackTranslator(assetKey, { ...options, locale })
|
|
52
480
|
});
|
|
53
481
|
function Locon({
|
|
54
482
|
children,
|
|
@@ -59,82 +487,89 @@ function Locon({
|
|
|
59
487
|
autodetect = true
|
|
60
488
|
}) {
|
|
61
489
|
const resolvedProjectLocale = projectLocale || defaultLocale;
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
if (autodetect) {
|
|
67
|
-
const systemLocale = (0, import_getSystemLanguage.default)(Object.keys(assets));
|
|
68
|
-
if (systemLocale && assets[systemLocale]) {
|
|
69
|
-
return systemLocale;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return defaultLocale;
|
|
73
|
-
});
|
|
74
|
-
const getAssets = (0, import_react.useCallback)(() => {
|
|
75
|
-
const currentAssets = assets[currentLocale] ?? assets[defaultLocale];
|
|
76
|
-
return currentAssets ?? {};
|
|
77
|
-
}, [assets, currentLocale, defaultLocale]);
|
|
78
|
-
const getAsset = (0, import_react.useCallback)(
|
|
79
|
-
(assetKey) => {
|
|
80
|
-
const assetsObj = getAssets();
|
|
81
|
-
return assetsObj[assetKey] ?? "";
|
|
82
|
-
},
|
|
83
|
-
[getAssets]
|
|
490
|
+
const locales = (0, import_react2.useMemo)(() => Object.keys(assets), [assets]);
|
|
491
|
+
const systemLocale = (0, import_react2.useMemo)(() => autodetect ? getSystemLanguage_default(locales) : null, [autodetect, locales]);
|
|
492
|
+
const [currentLocale, setCurrentLocale] = (0, import_react2.useState)(
|
|
493
|
+
() => resolveLocale_default({ assets, currentLocale: currentLocaleProps, defaultLocale, autodetect, systemLocale })
|
|
84
494
|
);
|
|
85
|
-
const setCurrentLocaleHandler = (0,
|
|
495
|
+
const setCurrentLocaleHandler = (0, import_react2.useCallback)(
|
|
86
496
|
(locale) => {
|
|
497
|
+
if (locale === null) {
|
|
498
|
+
setCurrentLocale(resolveLocale_default({ assets, defaultLocale, autodetect, systemLocale }));
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
87
501
|
if (assets[locale]) {
|
|
88
502
|
setCurrentLocale(locale);
|
|
89
503
|
} else {
|
|
90
504
|
console.warn(`[locon] Locale "${locale}" not found in assets.`);
|
|
91
505
|
}
|
|
92
506
|
},
|
|
93
|
-
[assets]
|
|
507
|
+
[assets, systemLocale, defaultLocale, autodetect]
|
|
94
508
|
);
|
|
95
|
-
const
|
|
96
|
-
(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
},
|
|
104
|
-
[assets, getAsset, resolvedProjectLocale]
|
|
509
|
+
const l = (0, import_react2.useMemo)(
|
|
510
|
+
() => createTranslator_default({
|
|
511
|
+
assets,
|
|
512
|
+
locale: currentLocale,
|
|
513
|
+
defaultLocale,
|
|
514
|
+
projectLocale: resolvedProjectLocale
|
|
515
|
+
}),
|
|
516
|
+
[assets, currentLocale, defaultLocale, resolvedProjectLocale]
|
|
105
517
|
);
|
|
106
|
-
const
|
|
107
|
-
(assetKey) => {
|
|
108
|
-
|
|
109
|
-
return "";
|
|
110
|
-
}
|
|
111
|
-
const asset = getAsset(assetKey) || getAssetByValue(assetKey) || getAssetByValue(assetKey, defaultLocale);
|
|
112
|
-
return asset ?? assetKey;
|
|
113
|
-
},
|
|
114
|
-
[getAsset, getAssetByValue, defaultLocale]
|
|
518
|
+
const lIn = (0, import_react2.useCallback)(
|
|
519
|
+
(locale, assetKey, options) => l(assetKey, { ...options, locale }),
|
|
520
|
+
[l]
|
|
115
521
|
);
|
|
116
|
-
(0,
|
|
117
|
-
if (currentLocaleProps) {
|
|
118
|
-
|
|
522
|
+
(0, import_react2.useEffect)(() => {
|
|
523
|
+
if (currentLocaleProps === void 0) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
if (currentLocaleProps === null) {
|
|
527
|
+
setCurrentLocale(resolveLocale_default({ assets, defaultLocale, autodetect, systemLocale }));
|
|
528
|
+
return;
|
|
119
529
|
}
|
|
120
|
-
|
|
121
|
-
|
|
530
|
+
setCurrentLocale((locale) => locale === currentLocaleProps ? locale : currentLocaleProps);
|
|
531
|
+
}, [assets, currentLocaleProps, systemLocale, defaultLocale, autodetect]);
|
|
532
|
+
const value = (0, import_react2.useMemo)(
|
|
122
533
|
() => ({
|
|
123
534
|
assets,
|
|
535
|
+
locales,
|
|
124
536
|
currentLocale,
|
|
125
537
|
defaultLocale,
|
|
538
|
+
projectLocale: resolvedProjectLocale,
|
|
539
|
+
systemLocale,
|
|
540
|
+
isRTL: isRtlLocale(currentLocale),
|
|
126
541
|
autodetect,
|
|
127
542
|
l,
|
|
543
|
+
lIn,
|
|
128
544
|
setLocale: setCurrentLocaleHandler
|
|
129
545
|
}),
|
|
130
|
-
[
|
|
546
|
+
[
|
|
547
|
+
assets,
|
|
548
|
+
locales,
|
|
549
|
+
currentLocale,
|
|
550
|
+
defaultLocale,
|
|
551
|
+
resolvedProjectLocale,
|
|
552
|
+
systemLocale,
|
|
553
|
+
autodetect,
|
|
554
|
+
l,
|
|
555
|
+
lIn,
|
|
556
|
+
setCurrentLocaleHandler
|
|
557
|
+
]
|
|
131
558
|
);
|
|
132
|
-
return /* @__PURE__ */ (0,
|
|
559
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LoconContext, { value, children });
|
|
133
560
|
}
|
|
134
|
-
var
|
|
561
|
+
var index_default = Locon;
|
|
135
562
|
// Annotate the CommonJS export names for ESM import in node:
|
|
136
563
|
0 && (module.exports = {
|
|
137
564
|
LText,
|
|
138
565
|
LoconContext,
|
|
566
|
+
RTL_LANGUAGES,
|
|
567
|
+
RTL_SCRIPTS,
|
|
568
|
+
applyRTL,
|
|
569
|
+
createTranslator,
|
|
570
|
+
getSystemLanguage,
|
|
571
|
+
intlLocale,
|
|
572
|
+
isRtlLocale,
|
|
573
|
+
resolveLocale,
|
|
139
574
|
useLocon
|
|
140
575
|
});
|