@gradio/core 0.16.0 → 0.17.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/CHANGELOG.md +52 -0
- package/dist/src/Blocks.svelte +6 -2
- package/dist/src/Render.svelte +2 -2
- package/dist/src/RenderComponent.svelte +21 -1
- package/dist/src/api_docs/ApiDocs.svelte +18 -3
- package/dist/src/gradio_helper.d.ts +1 -11
- package/dist/src/gradio_helper.js +3 -19
- package/dist/src/i18n.d.ts +12 -5
- package/dist/src/i18n.js +93 -12
- package/dist/src/init.js +36 -20
- package/dist/src/lang/en.json +2 -1
- package/dist/src/lang/es.json +2 -1
- package/dist/src/lang/fr.json +2 -1
- package/dist/src/lang/ja.json +2 -1
- package/dist/src/lang/ko.json +2 -1
- package/dist/src/lang/lt.json +2 -1
- package/dist/src/lang/nb.json +2 -1
- package/dist/src/lang/nl.json +2 -1
- package/dist/src/lang/pl.json +2 -1
- package/dist/src/lang/pt-BR.json +1 -0
- package/dist/src/lang/pt.json +2 -1
- package/dist/src/lang/ro.json +2 -1
- package/dist/src/lang/ru.json +2 -1
- package/dist/src/lang/sv.json +2 -1
- package/dist/src/lang/ta.json +2 -1
- package/dist/src/lang/th.json +2 -1
- package/dist/src/lang/tr.json +2 -1
- package/dist/src/lang/uk.json +2 -1
- package/dist/src/lang/ur.json +2 -1
- package/dist/src/lang/uz.json +2 -1
- package/dist/src/lang/zh-CN.json +2 -1
- package/dist/src/lang/zh-TW.json +2 -1
- package/package.json +53 -53
- package/src/Blocks.svelte +7 -3
- package/src/Render.svelte +2 -2
- package/src/RenderComponent.svelte +21 -1
- package/src/api_docs/ApiDocs.svelte +19 -3
- package/src/gradio_helper.ts +5 -21
- package/src/i18n.test.ts +120 -1
- package/src/i18n.ts +126 -24
- package/src/init.ts +47 -26
- package/src/lang/en.json +2 -1
- package/src/lang/es.json +2 -1
- package/src/lang/fr.json +2 -1
- package/src/lang/ja.json +2 -1
- package/src/lang/ko.json +2 -1
- package/src/lang/lt.json +2 -1
- package/src/lang/nb.json +2 -1
- package/src/lang/nl.json +2 -1
- package/src/lang/pl.json +2 -1
- package/src/lang/pt-BR.json +1 -0
- package/src/lang/pt.json +2 -1
- package/src/lang/ro.json +2 -1
- package/src/lang/ru.json +2 -1
- package/src/lang/sv.json +2 -1
- package/src/lang/ta.json +2 -1
- package/src/lang/th.json +2 -1
- package/src/lang/tr.json +2 -1
- package/src/lang/uk.json +2 -1
- package/src/lang/ur.json +2 -1
- package/src/lang/uz.json +2 -1
- package/src/lang/zh-CN.json +2 -1
- package/src/lang/zh-TW.json +2 -1
package/dist/src/lang/ta.json
CHANGED
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"runtime_error": "இயக்க நேர பிழை உள்ளது",
|
|
98
98
|
"space_not_working": "\"Space செயல்படவில்லை ஏனெனில்\" {0}",
|
|
99
99
|
"space_paused": "Space இடைநிறுத்தப்பட்டுள்ளது",
|
|
100
|
-
"use_via_api": "API மூலம் பயன்படுத்தவும்"
|
|
100
|
+
"use_via_api": "API மூலம் பயன்படுத்தவும்",
|
|
101
|
+
"use_via_api_or_mcp": "API அல்லது MCP மூலம் பயன்படுத்தவும்"
|
|
101
102
|
},
|
|
102
103
|
"file": {
|
|
103
104
|
"uploading": "பதிவேற்றுகிறது..."
|
package/dist/src/lang/th.json
CHANGED
|
@@ -87,7 +87,8 @@
|
|
|
87
87
|
"runtime_error": "เกิดข้อผิดพลาดขณะทำงาน",
|
|
88
88
|
"space_not_working": "\"Space ใช้งานไม่ได้เนื่องจาก\" {0}",
|
|
89
89
|
"space_paused": "Space ถูกหยุดชั่วคราว",
|
|
90
|
-
"use_via_api": "ใช้งานผ่าน API"
|
|
90
|
+
"use_via_api": "ใช้งานผ่าน API",
|
|
91
|
+
"use_via_api_or_mcp": "ใช้งานผ่าน API หรือ MCP"
|
|
91
92
|
},
|
|
92
93
|
"file": {
|
|
93
94
|
"uploading": "กำลังอัปโหลด..."
|
package/dist/src/lang/tr.json
CHANGED
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"runtime_error": "Bir çalışma zamanı hatası var",
|
|
98
98
|
"space_not_working": "\"Space çalışmıyor çünkü\" {0}",
|
|
99
99
|
"space_paused": "Space duraklatıldı",
|
|
100
|
-
"use_via_api": "API üzerinden kullan"
|
|
100
|
+
"use_via_api": "API üzerinden kullan",
|
|
101
|
+
"use_via_api_or_mcp": "API veya MCP üzerinden kullan"
|
|
101
102
|
},
|
|
102
103
|
"file": {
|
|
103
104
|
"uploading": "Yükleniyor..."
|
package/dist/src/lang/uk.json
CHANGED
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"runtime_error": "Є помилка виконання",
|
|
98
98
|
"space_not_working": "\"Space не працює, оскільки\" {0}",
|
|
99
99
|
"space_paused": "Space призупинено",
|
|
100
|
-
"use_via_api": "Використовувати через API"
|
|
100
|
+
"use_via_api": "Використовувати через API",
|
|
101
|
+
"use_via_api_or_mcp": "Використовувати через API або MCP"
|
|
101
102
|
},
|
|
102
103
|
"file": {
|
|
103
104
|
"uploading": "Завантаження..."
|
package/dist/src/lang/ur.json
CHANGED
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"runtime_error": "رن ٹائم میں خطا ہے",
|
|
98
98
|
"space_not_working": "\"Space کام نہیں کر رہا ہے کیونکہ\" {0}",
|
|
99
99
|
"space_paused": "Space موقوف ہے",
|
|
100
|
-
"use_via_api": "API کے ذریعے استعمال کریں"
|
|
100
|
+
"use_via_api": "API کے ذریعے استعمال کریں",
|
|
101
|
+
"use_via_api_or_mcp": "API یا MCP کے ذریعے استعمال کریں"
|
|
101
102
|
},
|
|
102
103
|
"file": {
|
|
103
104
|
"uploading": "اپلوڈ ہو رہا ہے..."
|
package/dist/src/lang/uz.json
CHANGED
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"runtime_error": "Bajarilish vaqti xatosi mavjud",
|
|
98
98
|
"space_not_working": "\"Space ishlamayapti, chunki\" {0}",
|
|
99
99
|
"space_paused": "Space to'xtatilgan",
|
|
100
|
-
"use_via_api": "API orqali foydalaning"
|
|
100
|
+
"use_via_api": "API orqali foydalaning",
|
|
101
|
+
"use_via_api_or_mcp": "API yoki MCP orqali foydalaning"
|
|
101
102
|
},
|
|
102
103
|
"file": {
|
|
103
104
|
"uploading": "Yuklanmoqda..."
|
package/dist/src/lang/zh-CN.json
CHANGED
|
@@ -87,7 +87,8 @@
|
|
|
87
87
|
"runtime_error": "存在运行时错误",
|
|
88
88
|
"space_not_working": "\"Space 无法工作,原因:\" {0}",
|
|
89
89
|
"space_paused": "Space 已暂停",
|
|
90
|
-
"use_via_api": "通过 API 使用"
|
|
90
|
+
"use_via_api": "通过 API 使用",
|
|
91
|
+
"use_via_api_or_mcp": "通过 API 或 MCP 使用"
|
|
91
92
|
},
|
|
92
93
|
"file": {
|
|
93
94
|
"uploading": "正在上传..."
|
package/dist/src/lang/zh-TW.json
CHANGED
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"runtime_error": "有執行時錯誤",
|
|
98
98
|
"space_not_working": "\"Space 無法運作,因為\" {0}",
|
|
99
99
|
"space_paused": "Space 已暫停",
|
|
100
|
-
"use_via_api": "透過 API 使用"
|
|
100
|
+
"use_via_api": "透過 API 使用",
|
|
101
|
+
"use_via_api_or_mcp": "透過 API 或 MCP 使用"
|
|
101
102
|
},
|
|
102
103
|
"file": {
|
|
103
104
|
"uploading": "上傳中..."
|
package/package.json
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"devDependencies": {
|
|
6
|
-
"@gradio/accordion": "^0.5.
|
|
7
|
-
"@gradio/
|
|
8
|
-
"@gradio/
|
|
9
|
-
"@gradio/
|
|
10
|
-
"@gradio/box": "^0.2.
|
|
11
|
-
"@gradio/
|
|
12
|
-
"@gradio/
|
|
13
|
-
"@gradio/checkboxgroup": "^0.6.
|
|
14
|
-
"@gradio/
|
|
15
|
-
"@gradio/
|
|
16
|
-
"@gradio/
|
|
17
|
-
"@gradio/colorpicker": "^0.4.
|
|
6
|
+
"@gradio/accordion": "^0.5.15",
|
|
7
|
+
"@gradio/annotatedimage": "^0.9.19",
|
|
8
|
+
"@gradio/atoms": "^0.16.1",
|
|
9
|
+
"@gradio/audio": "^0.17.14",
|
|
10
|
+
"@gradio/box": "^0.2.19",
|
|
11
|
+
"@gradio/chatbot": "^0.26.7",
|
|
12
|
+
"@gradio/button": "^0.5.0",
|
|
13
|
+
"@gradio/checkboxgroup": "^0.6.21",
|
|
14
|
+
"@gradio/client": "^1.15.0",
|
|
15
|
+
"@gradio/checkbox": "^0.4.21",
|
|
16
|
+
"@gradio/code": "^0.14.4",
|
|
17
|
+
"@gradio/colorpicker": "^0.4.21",
|
|
18
18
|
"@gradio/column": "^0.2.0",
|
|
19
|
-
"@gradio/dataframe": "^0.17.
|
|
20
|
-
"@gradio/dataset": "^0.4.
|
|
21
|
-
"@gradio/datetime": "^0.3.
|
|
22
|
-
"@gradio/
|
|
23
|
-
"@gradio/
|
|
24
|
-
"@gradio/
|
|
25
|
-
"@gradio/
|
|
26
|
-
"@gradio/
|
|
27
|
-
"@gradio/fileexplorer": "^0.5.
|
|
28
|
-
"@gradio/
|
|
29
|
-
"@gradio/
|
|
30
|
-
"@gradio/html": "^0.6.
|
|
31
|
-
"@gradio/icons": "^0.12.0",
|
|
19
|
+
"@gradio/dataframe": "^0.17.12",
|
|
20
|
+
"@gradio/dataset": "^0.4.19",
|
|
21
|
+
"@gradio/datetime": "^0.3.13",
|
|
22
|
+
"@gradio/downloadbutton": "^0.4.0",
|
|
23
|
+
"@gradio/dropdown": "^0.9.21",
|
|
24
|
+
"@gradio/file": "^0.12.18",
|
|
25
|
+
"@gradio/form": "^0.2.19",
|
|
26
|
+
"@gradio/fallback": "^0.4.21",
|
|
27
|
+
"@gradio/fileexplorer": "^0.5.29",
|
|
28
|
+
"@gradio/highlightedtext": "^0.9.4",
|
|
29
|
+
"@gradio/gallery": "^0.15.19",
|
|
30
|
+
"@gradio/html": "^0.6.13",
|
|
32
31
|
"@gradio/group": "^0.2.0",
|
|
33
|
-
"@gradio/
|
|
34
|
-
"@gradio/image": "^0.22.
|
|
35
|
-
"@gradio/
|
|
36
|
-
"@gradio/
|
|
32
|
+
"@gradio/icons": "^0.12.0",
|
|
33
|
+
"@gradio/image": "^0.22.6",
|
|
34
|
+
"@gradio/imageeditor": "^0.15.0",
|
|
35
|
+
"@gradio/imageslider": "^0.2.2",
|
|
36
|
+
"@gradio/label": "^0.5.13",
|
|
37
|
+
"@gradio/json": "^0.5.22",
|
|
37
38
|
"@gradio/browserstate": "^0.3.2",
|
|
38
|
-
"@gradio/markdown": "^0.13.
|
|
39
|
-
"@gradio/
|
|
40
|
-
"@gradio/
|
|
41
|
-
"@gradio/paramviewer": "^0.7.
|
|
42
|
-
"@gradio/number": "^0.5.
|
|
43
|
-
"@gradio/
|
|
44
|
-
"@gradio/plot": "^0.9.
|
|
45
|
-
"@gradio/
|
|
46
|
-
"@gradio/radio": "^0.7.3",
|
|
39
|
+
"@gradio/markdown": "^0.13.12",
|
|
40
|
+
"@gradio/multimodaltextbox": "^0.10.6",
|
|
41
|
+
"@gradio/nativeplot": "^0.5.16",
|
|
42
|
+
"@gradio/paramviewer": "^0.7.9",
|
|
43
|
+
"@gradio/number": "^0.5.21",
|
|
44
|
+
"@gradio/model3d": "^0.14.13",
|
|
45
|
+
"@gradio/plot": "^0.9.16",
|
|
46
|
+
"@gradio/radio": "^0.7.4",
|
|
47
47
|
"@gradio/row": "^0.2.1",
|
|
48
|
-
"@gradio/sidebar": "^0.1.
|
|
49
|
-
"@gradio/simpledropdown": "^0.3.
|
|
50
|
-
"@gradio/
|
|
51
|
-
"@gradio/simpletextbox": "^0.3.
|
|
52
|
-
"@gradio/
|
|
53
|
-
"@gradio/slider": "^0.6.
|
|
48
|
+
"@gradio/sidebar": "^0.1.13",
|
|
49
|
+
"@gradio/simpledropdown": "^0.3.21",
|
|
50
|
+
"@gradio/sketchbox": "^0.6.8",
|
|
51
|
+
"@gradio/simpletextbox": "^0.3.21",
|
|
52
|
+
"@gradio/simpleimage": "^0.8.29",
|
|
53
|
+
"@gradio/slider": "^0.6.9",
|
|
54
|
+
"@gradio/statustracker": "^0.10.11",
|
|
54
55
|
"@gradio/state": "^0.1.2",
|
|
55
|
-
"@gradio/
|
|
56
|
-
"@gradio/
|
|
57
|
-
"@gradio/
|
|
56
|
+
"@gradio/tabitem": "^0.4.4",
|
|
57
|
+
"@gradio/tabs": "^0.4.4",
|
|
58
|
+
"@gradio/textbox": "^0.10.11",
|
|
58
59
|
"@gradio/theme": "^0.4.0",
|
|
59
|
-
"@gradio/textbox": "^0.10.10",
|
|
60
|
-
"@gradio/upload": "^0.16.3",
|
|
61
|
-
"@gradio/uploadbutton": "^0.8.17",
|
|
62
60
|
"@gradio/timer": "^0.4.5",
|
|
61
|
+
"@gradio/upload": "^0.16.5",
|
|
62
|
+
"@gradio/uploadbutton": "^0.9.0",
|
|
63
63
|
"@gradio/utils": "^0.10.2",
|
|
64
|
-
"@gradio/
|
|
65
|
-
"@gradio/
|
|
64
|
+
"@gradio/wasm": "^0.18.1",
|
|
65
|
+
"@gradio/video": "^0.14.14"
|
|
66
66
|
},
|
|
67
67
|
"msw": {
|
|
68
68
|
"workerDirectory": "public"
|
package/src/Blocks.svelte
CHANGED
|
@@ -26,8 +26,6 @@
|
|
|
26
26
|
StatusMessage
|
|
27
27
|
} from "@gradio/client";
|
|
28
28
|
|
|
29
|
-
setupi18n();
|
|
30
|
-
|
|
31
29
|
export let root: string;
|
|
32
30
|
export let components: ComponentMeta[];
|
|
33
31
|
export let layout: LayoutNode;
|
|
@@ -52,6 +50,8 @@
|
|
|
52
50
|
export let initial_layout: ComponentMeta | undefined = undefined;
|
|
53
51
|
export let css: string | null | undefined = null;
|
|
54
52
|
|
|
53
|
+
setupi18n(app.config?.i18n_translations ?? undefined);
|
|
54
|
+
|
|
55
55
|
let {
|
|
56
56
|
layout: _layout,
|
|
57
57
|
targets,
|
|
@@ -822,7 +822,11 @@
|
|
|
822
822
|
}}
|
|
823
823
|
class="show-api"
|
|
824
824
|
>
|
|
825
|
-
{
|
|
825
|
+
{#if app.config?.mcp_server}
|
|
826
|
+
{$_("errors.use_via_api_or_mcp")}
|
|
827
|
+
{:else}
|
|
828
|
+
{$_("errors.use_via_api")}
|
|
829
|
+
{/if}
|
|
826
830
|
<img src={api_logo} alt={$_("common.logo")} />
|
|
827
831
|
</button>
|
|
828
832
|
<div class="divider show-api-divider">·</div>
|
package/src/Render.svelte
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Gradio,
|
|
2
|
+
import { Gradio, reactive_formatter } from "./gradio_helper";
|
|
3
3
|
import { onMount, createEventDispatcher, setContext } from "svelte";
|
|
4
4
|
import type { ComponentMeta, ThemeMode } from "./types";
|
|
5
5
|
import type { Client } from "@gradio/client";
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
root,
|
|
71
71
|
autoscroll,
|
|
72
72
|
max_file_size,
|
|
73
|
-
|
|
73
|
+
$reactive_formatter,
|
|
74
74
|
client,
|
|
75
75
|
load_component
|
|
76
76
|
);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<svelte:options immutable={true} />
|
|
2
2
|
|
|
3
3
|
<script lang="ts">
|
|
4
|
-
import type { Gradio } from "./gradio_helper";
|
|
5
4
|
import type { ComponentMeta, ThemeMode } from "./types";
|
|
6
5
|
import type { SvelteComponent, ComponentType } from "svelte";
|
|
6
|
+
import { translate_if_needed } from "./i18n";
|
|
7
7
|
// @ts-ignore
|
|
8
8
|
import { bind, binding_callbacks } from "svelte/internal";
|
|
9
9
|
|
|
@@ -50,6 +50,26 @@
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const _component = wrap(component);
|
|
53
|
+
|
|
54
|
+
const supported_props = [
|
|
55
|
+
"description",
|
|
56
|
+
"info",
|
|
57
|
+
"title",
|
|
58
|
+
"placeholder",
|
|
59
|
+
"value",
|
|
60
|
+
"label"
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
function translate_prop(obj: SvelteRestProps): void {
|
|
64
|
+
for (const key in obj) {
|
|
65
|
+
if (supported_props.includes(key as string)) {
|
|
66
|
+
obj[key] = translate_if_needed(obj[key]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
$: translate_prop($$restProps);
|
|
72
|
+
$: value = translate_if_needed(value);
|
|
53
73
|
</script>
|
|
54
74
|
|
|
55
75
|
<!-- {#if visible} -->
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
const bash_docs =
|
|
36
36
|
"https://www.gradio.app/guides/querying-gradio-apps-with-curl";
|
|
37
37
|
const spaces_docs_suffix = "#connecting-to-a-hugging-face-space";
|
|
38
|
+
const mcp_docs =
|
|
39
|
+
"https://www.gradio.app/guides/building-mcp-server-with-gradio";
|
|
38
40
|
|
|
39
41
|
let api_count = dependencies.filter(
|
|
40
42
|
(dependency) => dependency.show_api
|
|
@@ -343,7 +345,12 @@
|
|
|
343
345
|
mcpServers: {
|
|
344
346
|
gradio: {
|
|
345
347
|
command: "npx",
|
|
346
|
-
args: [
|
|
348
|
+
args: [
|
|
349
|
+
"mcp-remote",
|
|
350
|
+
mcp_server_url,
|
|
351
|
+
"--transport",
|
|
352
|
+
"sse-only"
|
|
353
|
+
]
|
|
347
354
|
}
|
|
348
355
|
}
|
|
349
356
|
},
|
|
@@ -358,7 +365,12 @@
|
|
|
358
365
|
mcpServers: {
|
|
359
366
|
gradio: {
|
|
360
367
|
command: "npx",
|
|
361
|
-
|
|
368
|
+
args: [
|
|
369
|
+
"mcp-remote",
|
|
370
|
+
mcp_server_url,
|
|
371
|
+
"--transport",
|
|
372
|
+
"sse-only"
|
|
373
|
+
]
|
|
362
374
|
}
|
|
363
375
|
}
|
|
364
376
|
},
|
|
@@ -369,7 +381,11 @@
|
|
|
369
381
|
</code>
|
|
370
382
|
</Block>
|
|
371
383
|
<p> </p>
|
|
372
|
-
<p
|
|
384
|
+
<p>
|
|
385
|
+
<a href={mcp_docs} target="_blank">
|
|
386
|
+
Read more about MCP in the Gradio docs
|
|
387
|
+
</a>
|
|
388
|
+
</p>
|
|
373
389
|
{:else}
|
|
374
390
|
This Gradio app can also serve as an MCP server, with an MCP
|
|
375
391
|
tool corresponding to each API endpoint. To enable this, launch
|
package/src/gradio_helper.ts
CHANGED
|
@@ -1,28 +1,16 @@
|
|
|
1
|
-
import { format, _ } from "svelte-i18n";
|
|
2
|
-
import { get } from "svelte/store";
|
|
3
1
|
import { all_common_keys } from "./i18n";
|
|
4
|
-
|
|
2
|
+
import { _ } from "svelte-i18n";
|
|
3
|
+
import { get, derived } from "svelte/store";
|
|
5
4
|
export { Gradio } from "@gradio/utils";
|
|
5
|
+
|
|
6
6
|
export type I18nFormatter = typeof formatter;
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* i18n formatter with fallback to svelte-i18n's format function.
|
|
10
|
-
*
|
|
11
|
-
* @param value - The string to translate or format
|
|
12
|
-
* @returns The translated string
|
|
13
|
-
*
|
|
14
|
-
* This formatter attempts translation in the following order:
|
|
15
|
-
* 1. Direct translation of the input string
|
|
16
|
-
* 2. Checks if input matches any common key names
|
|
17
|
-
* 3. Falls back to svelte-i18n's format function
|
|
18
|
-
*/
|
|
19
8
|
export function formatter(value: string | null | undefined): string {
|
|
20
9
|
if (value == null) {
|
|
21
10
|
return "";
|
|
22
11
|
}
|
|
23
12
|
const string_value = String(value);
|
|
24
13
|
const translate = get(_);
|
|
25
|
-
const initial_formatter = get(format);
|
|
26
14
|
|
|
27
15
|
let direct_translation = translate(string_value);
|
|
28
16
|
|
|
@@ -45,11 +33,7 @@ export function formatter(value: string | null | undefined): string {
|
|
|
45
33
|
}
|
|
46
34
|
}
|
|
47
35
|
|
|
48
|
-
// fall back to the svelte-i18n formatter to maintain compatibility
|
|
49
|
-
const formatted = initial_formatter(string_value);
|
|
50
|
-
if (formatted !== string_value) {
|
|
51
|
-
return formatted;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
36
|
return string_value;
|
|
55
37
|
}
|
|
38
|
+
|
|
39
|
+
export const reactive_formatter = derived(_, () => formatter);
|
package/src/i18n.test.ts
CHANGED
|
@@ -1,7 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
describe,
|
|
3
|
+
test,
|
|
4
|
+
expect,
|
|
5
|
+
assert,
|
|
6
|
+
vi,
|
|
7
|
+
beforeEach,
|
|
8
|
+
afterEach
|
|
9
|
+
} from "vitest";
|
|
2
10
|
import { process_langs } from "./i18n";
|
|
3
11
|
import languagesByAnyCode from "wikidata-lang/indexes/by_any_code";
|
|
4
12
|
import BCP47 from "./lang/BCP47_codes";
|
|
13
|
+
import {
|
|
14
|
+
translate_if_needed,
|
|
15
|
+
get_initial_locale,
|
|
16
|
+
load_translations,
|
|
17
|
+
changeLocale,
|
|
18
|
+
is_translation_metadata
|
|
19
|
+
} from "./i18n";
|
|
20
|
+
|
|
21
|
+
vi.mock("svelte-i18n", () => ({
|
|
22
|
+
locale: { set: vi.fn() },
|
|
23
|
+
_: vi.fn((key) => `translated_${key}`),
|
|
24
|
+
addMessages: vi.fn(),
|
|
25
|
+
init: vi.fn().mockResolvedValue(undefined)
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
vi.mock("svelte/store", () => ({
|
|
29
|
+
get: vi.fn((store) => store),
|
|
30
|
+
derived: vi.fn()
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
import { locale, init, addMessages } from "svelte-i18n";
|
|
5
34
|
|
|
6
35
|
describe("i18n", () => {
|
|
7
36
|
test("languages are loaded correctly", () => {
|
|
@@ -24,4 +53,94 @@ describe("i18n", () => {
|
|
|
24
53
|
assert.ok(translation.common);
|
|
25
54
|
});
|
|
26
55
|
});
|
|
56
|
+
|
|
57
|
+
describe("basic functions", () => {
|
|
58
|
+
test("translate_if_needed handles regular strings", () => {
|
|
59
|
+
const regularString = "hello world";
|
|
60
|
+
expect(translate_if_needed(regularString)).toBe(regularString);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("locale management", () => {
|
|
65
|
+
test("get_initial_locale returns browser locale when available", () => {
|
|
66
|
+
const result = get_initial_locale("fr", ["en", "fr", "de"]);
|
|
67
|
+
expect(result).toBe("fr");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("get_initial_locale falls back to fallback locale when browser locale not available", () => {
|
|
71
|
+
const result = get_initial_locale("es", ["en", "fr", "de"]);
|
|
72
|
+
expect(result).toBe("en");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("get_initial_locale falls back to fallback locale when browser locale is null", () => {
|
|
76
|
+
const result = get_initial_locale(null, ["en", "fr", "de"]);
|
|
77
|
+
expect(result).toBe("en");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("get_initial_locale uses custom fallback locale when provided", () => {
|
|
81
|
+
const result = get_initial_locale("es", ["en", "fr", "de"], "de");
|
|
82
|
+
expect(result).toBe("de");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("i18n setup and initialization", () => {
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
vi.clearAllMocks();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
afterEach(() => {
|
|
92
|
+
vi.resetAllMocks();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("load_translations adds messages for each language", () => {
|
|
96
|
+
const mockAddMessages = addMessages as unknown as ReturnType<
|
|
97
|
+
typeof vi.fn
|
|
98
|
+
>;
|
|
99
|
+
|
|
100
|
+
const custom_translations = {
|
|
101
|
+
en: {
|
|
102
|
+
greeting: "Hello"
|
|
103
|
+
},
|
|
104
|
+
fr: {
|
|
105
|
+
greeting: "Bonjour"
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
load_translations(custom_translations);
|
|
110
|
+
|
|
111
|
+
expect(mockAddMessages).toHaveBeenCalledTimes(2);
|
|
112
|
+
expect(mockAddMessages).toHaveBeenCalledWith(
|
|
113
|
+
"en",
|
|
114
|
+
custom_translations.en
|
|
115
|
+
);
|
|
116
|
+
expect(mockAddMessages).toHaveBeenCalledWith(
|
|
117
|
+
"fr",
|
|
118
|
+
custom_translations.fr
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("changeLocale sets the locale correctly", () => {
|
|
123
|
+
const mockSetLocale = locale.set as unknown as ReturnType<typeof vi.fn>;
|
|
124
|
+
|
|
125
|
+
changeLocale("fr");
|
|
126
|
+
|
|
127
|
+
expect(mockSetLocale).toHaveBeenCalledWith("fr");
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe("translation metadata handling", () => {
|
|
132
|
+
test("is_translation_metadata identifies valid metadata objects", () => {
|
|
133
|
+
expect(
|
|
134
|
+
is_translation_metadata({
|
|
135
|
+
__type__: "translation_metadata" as const,
|
|
136
|
+
key: "test.key"
|
|
137
|
+
})
|
|
138
|
+
).toBe(true);
|
|
139
|
+
expect(is_translation_metadata({ key: "test.key" })).toBe(false);
|
|
140
|
+
|
|
141
|
+
expect(Boolean(is_translation_metadata(null))).toBe(false);
|
|
142
|
+
expect(Boolean(is_translation_metadata(undefined))).toBe(false);
|
|
143
|
+
expect(Boolean(is_translation_metadata("not an object"))).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
27
146
|
});
|