@hua-labs/i18n-loaders 1.0.0 → 1.1.0-alpha.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/LICENSE +20 -20
- package/README.md +415 -415
- package/dist/api-loader.d.ts +24 -1
- package/dist/api-loader.d.ts.map +1 -1
- package/dist/api-loader.js +78 -1
- package/dist/api-loader.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/api-loader.ts +281 -199
- package/src/defaults.ts +63 -63
- package/src/index.ts +13 -12
- package/src/preload.ts +64 -64
- package/src/types.ts +56 -34
package/src/preload.ts
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
import { PreloadOptions, TranslationLoader } from './types';
|
|
2
|
-
|
|
3
|
-
const defaultLogger = console;
|
|
4
|
-
|
|
5
|
-
export async function preloadNamespaces(
|
|
6
|
-
language: string,
|
|
7
|
-
namespaces: string[],
|
|
8
|
-
loader: TranslationLoader,
|
|
9
|
-
options: PreloadOptions = {}
|
|
10
|
-
) {
|
|
11
|
-
const logger = options.logger ?? defaultLogger;
|
|
12
|
-
|
|
13
|
-
const results = await Promise.allSettled(
|
|
14
|
-
namespaces.map(async (namespace) => {
|
|
15
|
-
await loader(language, namespace);
|
|
16
|
-
return namespace;
|
|
17
|
-
})
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
const fulfilled = results.filter(
|
|
21
|
-
(result): result is PromiseFulfilledResult<string> =>
|
|
22
|
-
result.status === 'fulfilled'
|
|
23
|
-
);
|
|
24
|
-
const rejected = results.filter(
|
|
25
|
-
(result): result is PromiseRejectedResult => result.status === 'rejected'
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
if (fulfilled.length > 0) {
|
|
29
|
-
logger.log?.(
|
|
30
|
-
`[i18n-loaders] Preloaded ${fulfilled.length}/${namespaces.length} namespaces for ${language}`
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (rejected.length > 0 && !options.suppressErrors) {
|
|
35
|
-
logger.warn?.(
|
|
36
|
-
`[i18n-loaders] Failed to preload ${rejected.length} namespaces for ${language}`
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
fulfilled: fulfilled.map((result) => result.value),
|
|
42
|
-
rejected: rejected.map((result) => result.reason)
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export async function warmFallbackLanguages(
|
|
47
|
-
currentLanguage: string,
|
|
48
|
-
languages: string[],
|
|
49
|
-
namespaces: string[],
|
|
50
|
-
loader: TranslationLoader,
|
|
51
|
-
options: PreloadOptions = {}
|
|
52
|
-
) {
|
|
53
|
-
const targets = languages.filter((language) => language !== currentLanguage);
|
|
54
|
-
if (targets.length === 0) {
|
|
55
|
-
return [];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return Promise.all(
|
|
59
|
-
targets.map((language) =>
|
|
60
|
-
preloadNamespaces(language, namespaces, loader, options)
|
|
61
|
-
)
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
1
|
+
import { PreloadOptions, TranslationLoader } from './types';
|
|
2
|
+
|
|
3
|
+
const defaultLogger = console;
|
|
4
|
+
|
|
5
|
+
export async function preloadNamespaces(
|
|
6
|
+
language: string,
|
|
7
|
+
namespaces: string[],
|
|
8
|
+
loader: TranslationLoader,
|
|
9
|
+
options: PreloadOptions = {}
|
|
10
|
+
) {
|
|
11
|
+
const logger = options.logger ?? defaultLogger;
|
|
12
|
+
|
|
13
|
+
const results = await Promise.allSettled(
|
|
14
|
+
namespaces.map(async (namespace) => {
|
|
15
|
+
await loader(language, namespace);
|
|
16
|
+
return namespace;
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const fulfilled = results.filter(
|
|
21
|
+
(result): result is PromiseFulfilledResult<string> =>
|
|
22
|
+
result.status === 'fulfilled'
|
|
23
|
+
);
|
|
24
|
+
const rejected = results.filter(
|
|
25
|
+
(result): result is PromiseRejectedResult => result.status === 'rejected'
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (fulfilled.length > 0) {
|
|
29
|
+
logger.log?.(
|
|
30
|
+
`[i18n-loaders] Preloaded ${fulfilled.length}/${namespaces.length} namespaces for ${language}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (rejected.length > 0 && !options.suppressErrors) {
|
|
35
|
+
logger.warn?.(
|
|
36
|
+
`[i18n-loaders] Failed to preload ${rejected.length} namespaces for ${language}`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
fulfilled: fulfilled.map((result) => result.value),
|
|
42
|
+
rejected: rejected.map((result) => result.reason)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function warmFallbackLanguages(
|
|
47
|
+
currentLanguage: string,
|
|
48
|
+
languages: string[],
|
|
49
|
+
namespaces: string[],
|
|
50
|
+
loader: TranslationLoader,
|
|
51
|
+
options: PreloadOptions = {}
|
|
52
|
+
) {
|
|
53
|
+
const targets = languages.filter((language) => language !== currentLanguage);
|
|
54
|
+
if (targets.length === 0) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return Promise.all(
|
|
59
|
+
targets.map((language) =>
|
|
60
|
+
preloadNamespaces(language, namespaces, loader, options)
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
package/src/types.ts
CHANGED
|
@@ -1,34 +1,56 @@
|
|
|
1
|
-
export type TranslationRecord = Record<string, unknown>;
|
|
2
|
-
|
|
3
|
-
export type TranslationLoader = (
|
|
4
|
-
language: string,
|
|
5
|
-
namespace: string
|
|
6
|
-
) => Promise<TranslationRecord>;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
>;
|
|
34
|
-
|
|
1
|
+
export type TranslationRecord = Record<string, unknown>;
|
|
2
|
+
|
|
3
|
+
export type TranslationLoader = (
|
|
4
|
+
language: string,
|
|
5
|
+
namespace: string
|
|
6
|
+
) => Promise<TranslationRecord>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 캐시 무효화 함수 타입
|
|
10
|
+
*/
|
|
11
|
+
export interface CacheInvalidation {
|
|
12
|
+
/**
|
|
13
|
+
* 특정 언어/네임스페이스의 캐시 무효화
|
|
14
|
+
* @param language - 언어 코드 (선택적, 없으면 모든 언어)
|
|
15
|
+
* @param namespace - 네임스페이스 (선택적, 없으면 모든 네임스페이스)
|
|
16
|
+
*/
|
|
17
|
+
invalidate?: (language?: string, namespace?: string) => void;
|
|
18
|
+
/**
|
|
19
|
+
* 전체 캐시 클리어
|
|
20
|
+
*/
|
|
21
|
+
clear?: () => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ApiLoaderOptions {
|
|
25
|
+
translationApiPath?: string;
|
|
26
|
+
baseUrl?: string;
|
|
27
|
+
localFallbackBaseUrl?: string;
|
|
28
|
+
cacheTtlMs?: number;
|
|
29
|
+
disableCache?: boolean;
|
|
30
|
+
requestInit?:
|
|
31
|
+
| RequestInit
|
|
32
|
+
| ((language: string, namespace: string) => RequestInit | undefined);
|
|
33
|
+
fetcher?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
34
|
+
logger?: Pick<typeof console, 'log' | 'warn' | 'error'>;
|
|
35
|
+
/** 재시도 횟수 (기본값: 0, 재시도 안 함) */
|
|
36
|
+
retryCount?: number;
|
|
37
|
+
/** 재시도 지연 시간 (밀리초, 기본값: 1000) */
|
|
38
|
+
retryDelay?: number;
|
|
39
|
+
/**
|
|
40
|
+
* 개발 모드에서 자동 캐시 무효화
|
|
41
|
+
* 기본값: true (개발 모드에서만)
|
|
42
|
+
* 개발 중 번역 파일 변경 시 캐시를 자동으로 무효화하여 최신 번역을 즉시 반영
|
|
43
|
+
*/
|
|
44
|
+
autoInvalidateInDev?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface PreloadOptions {
|
|
48
|
+
logger?: Pick<typeof console, 'log' | 'warn'>;
|
|
49
|
+
suppressErrors?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type DefaultTranslations = Record<
|
|
53
|
+
string,
|
|
54
|
+
Record<string, TranslationRecord>
|
|
55
|
+
>;
|
|
56
|
+
|