@gradio/core 0.27.2 → 0.29.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 +71 -0
- package/dist/src/Blocks.svelte +84 -2
- package/dist/src/Embed.svelte +59 -26
- package/dist/src/Embed.svelte.d.ts +2 -2
- package/dist/src/Render.svelte +10 -5
- package/dist/src/RenderComponent.svelte.d.ts +1 -1
- package/dist/src/api_docs/CodeSnippet.svelte +10 -10
- package/dist/src/i18n.d.ts +2 -1
- package/dist/src/i18n.js +24 -5
- package/dist/src/init.js +48 -64
- package/dist/src/lang/ar.json +22 -14
- package/dist/src/lang/id.json +154 -0
- package/dist/src/navbar_store.d.ts +6 -0
- package/dist/src/navbar_store.js +2 -0
- package/dist/src/stores.d.ts +2 -0
- package/dist/src/stores.js +10 -0
- package/dist/src/stories/I18nMultiLanguageTest.stories.d.ts +0 -1
- package/dist/src/stories/I18nMultiLanguageTest.stories.js +1 -1
- package/dist/src/types.d.ts +1 -0
- package/package.json +61 -57
- package/src/Blocks.svelte +108 -2
- package/src/Embed.svelte +84 -28
- package/src/Render.svelte +15 -7
- package/src/RenderComponent.svelte +1 -1
- package/src/api_docs/CodeSnippet.svelte +10 -10
- package/src/i18n.ts +30 -7
- package/src/init.ts +62 -74
- package/src/lang/ar.json +22 -14
- package/src/lang/id.json +154 -0
- package/src/navbar_store.ts +9 -0
- package/src/stores.ts +19 -0
- package/src/stories/I18nMultiLanguageTest.stories.ts +1 -1
- package/src/types.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
1
|
# @gradio/core
|
|
2
2
|
|
|
3
|
+
## 0.29.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [#11894](https://github.com/gradio-app/gradio/pull/11894) [`cf10724`](https://github.com/gradio-app/gradio/commit/cf107246c104f3d8be1adf7a4c3d85558a0a5497) - Remove additional indentation in python API docs. Thanks @freddyaboulton!
|
|
8
|
+
- [#11858](https://github.com/gradio-app/gradio/pull/11858) [`3f8ea13`](https://github.com/gradio-app/gradio/commit/3f8ea13a8ca92abf0ad34392e403a449fda3c6c2) - remove lite. Thanks @pngwn!
|
|
9
|
+
- [#11902](https://github.com/gradio-app/gradio/pull/11902) [`6d39644`](https://github.com/gradio-app/gradio/commit/6d39644ee1000b04728eb4909cee405e7ee3b5b2) - Add navbar visibility controls and customization options. Thanks @abidlabs!
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
- [#11919](https://github.com/gradio-app/gradio/pull/11919) [`3b15f63`](https://github.com/gradio-app/gradio/commit/3b15f6370bc143c0acd91225574250bccf0a8877) - ensure spaces iframe resizes when images load. Thanks @pngwn!
|
|
14
|
+
- [#11784](https://github.com/gradio-app/gradio/pull/11784) [`d9dd3f5`](https://github.com/gradio-app/gradio/commit/d9dd3f54b7fb34cf7118e549d39fc63937ca3489) - Add "hidden" option to component's `visible` kwarg to render but visually hide the component. Thanks @pngwn!
|
|
15
|
+
- [#11866](https://github.com/gradio-app/gradio/pull/11866) [`02df670`](https://github.com/gradio-app/gradio/commit/02df670eccf365c253f38b682a3000fe316eef22) - Fix i18n when accept-language header contains multiple values. Thanks @freddyaboulton!
|
|
16
|
+
- [#11903](https://github.com/gradio-app/gradio/pull/11903) [`895d884`](https://github.com/gradio-app/gradio/commit/895d884a7345894f95df5f131d6517e935fd275a) - enhanced_the_arabic_translation. Thanks @makhlwf!
|
|
17
|
+
|
|
18
|
+
### Dependency updates
|
|
19
|
+
|
|
20
|
+
- @gradio/paramviewer@0.8.0
|
|
21
|
+
- @gradio/code@0.15.0
|
|
22
|
+
- @gradio/statustracker@0.11.1
|
|
23
|
+
- @gradio/tabitem@0.6.1
|
|
24
|
+
- @gradio/tabs@0.5.1
|
|
25
|
+
- @gradio/atoms@0.18.0
|
|
26
|
+
- @gradio/checkbox@0.4.30
|
|
27
|
+
- @gradio/client@1.19.0
|
|
28
|
+
- @gradio/upload@0.17.0
|
|
29
|
+
- @gradio/button@0.5.13
|
|
30
|
+
- @gradio/textbox@0.11.1
|
|
31
|
+
- @gradio/gallery@0.15.33
|
|
32
|
+
- @gradio/plot@0.9.24
|
|
33
|
+
- @gradio/image@0.23.0
|
|
34
|
+
- @gradio/column@0.2.2
|
|
35
|
+
- @gradio/dropdown@0.10.4
|
|
36
|
+
- @gradio/file@0.13.0
|
|
37
|
+
- @gradio/video@0.16.0
|
|
38
|
+
|
|
39
|
+
## 0.28.0
|
|
40
|
+
|
|
41
|
+
### Features
|
|
42
|
+
|
|
43
|
+
- [#11814](https://github.com/gradio-app/gradio/pull/11814) [`013784a`](https://github.com/gradio-app/gradio/commit/013784a7086047651e8e661a38bde7d5c7f10db7) - add validation support. Thanks @pngwn!
|
|
44
|
+
- [#11833](https://github.com/gradio-app/gradio/pull/11833) [`a446fcb`](https://github.com/gradio-app/gradio/commit/a446fcba6f3fe59c32194beb7f27fb6f80b61347) - Add gr.Navbar component for multipage apps. Thanks @abidlabs!
|
|
45
|
+
- [#11783](https://github.com/gradio-app/gradio/pull/11783) [`f407daf`](https://github.com/gradio-app/gradio/commit/f407daf8046f37e042ab8b86730ff0ab8d174bcf) - Add Walkthrough and Step compoents to facilitate multi-step workflows. Thanks @pngwn!
|
|
46
|
+
|
|
47
|
+
### Fixes
|
|
48
|
+
|
|
49
|
+
- [#11815](https://github.com/gradio-app/gradio/pull/11815) [`1a477c5`](https://github.com/gradio-app/gradio/commit/1a477c5202c13097d1089fb70a32a08db22d7660) - Fix i18n string visible during load and i18n not respecting HTML. Thanks @freddyaboulton!
|
|
50
|
+
- [#11749](https://github.com/gradio-app/gradio/pull/11749) [`70f4532`](https://github.com/gradio-app/gradio/commit/70f4532a4dc7576dbdbe1d0a43a05644a0dfcf43) - fix various iFrame related UI issues when deploying to spaces. Thanks @pngwn!
|
|
51
|
+
|
|
52
|
+
### Dependency updates
|
|
53
|
+
|
|
54
|
+
- @gradio/client@1.18.0
|
|
55
|
+
- @gradio/icons@0.14.0
|
|
56
|
+
- @gradio/atoms@0.17.0
|
|
57
|
+
- @gradio/statustracker@0.11.0
|
|
58
|
+
- @gradio/gallery@0.15.32
|
|
59
|
+
- @gradio/plot@0.9.23
|
|
60
|
+
- @gradio/upload@0.16.17
|
|
61
|
+
- @gradio/file@0.12.29
|
|
62
|
+
- @gradio/image@0.22.18
|
|
63
|
+
- @gradio/video@0.15.1
|
|
64
|
+
- @gradio/tabitem@0.6.0
|
|
65
|
+
- @gradio/tabs@0.5.0
|
|
66
|
+
- @gradio/code@0.14.16
|
|
67
|
+
- @gradio/paramviewer@0.7.16
|
|
68
|
+
- @gradio/column@0.2.1
|
|
69
|
+
- @gradio/textbox@0.11.0
|
|
70
|
+
- @gradio/dropdown@0.10.3
|
|
71
|
+
- @gradio/button@0.5.12
|
|
72
|
+
- @gradio/checkbox@0.4.29
|
|
73
|
+
|
|
3
74
|
## 0.27.2
|
|
4
75
|
|
|
5
76
|
### Features
|
package/dist/src/Blocks.svelte
CHANGED
|
@@ -193,6 +193,17 @@ async function handle_update(data, fn_index) {
|
|
|
193
193
|
}
|
|
194
194
|
});
|
|
195
195
|
update_value(updates);
|
|
196
|
+
updates.forEach((update) => {
|
|
197
|
+
const component = components.find((comp) => comp.id === update.id);
|
|
198
|
+
if (component && component.type === "navbar") {
|
|
199
|
+
import("./navbar_store").then(({ navbar_config }) => {
|
|
200
|
+
navbar_config.update((current) => ({
|
|
201
|
+
...current,
|
|
202
|
+
[update.prop]: update.value
|
|
203
|
+
}));
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|
|
196
207
|
await tick();
|
|
197
208
|
}
|
|
198
209
|
let submit_map = /* @__PURE__ */ new Map();
|
|
@@ -485,6 +496,40 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
|
|
|
485
496
|
}
|
|
486
497
|
}
|
|
487
498
|
function handle_status_update(message) {
|
|
499
|
+
if (message.code === "validation_error") {
|
|
500
|
+
const dep2 = dependencies.find((dep3) => dep3.id === message.fn_index);
|
|
501
|
+
if (dep2 === void 0 || message.message === void 0 || typeof message.message === "string") {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
const validation_error_data = [];
|
|
505
|
+
message.message.forEach((message2, i) => {
|
|
506
|
+
if (message2.is_valid) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
validation_error_data.push({
|
|
510
|
+
id: dep2.inputs[i],
|
|
511
|
+
prop: "validation_error",
|
|
512
|
+
value: message2.message
|
|
513
|
+
});
|
|
514
|
+
validation_error_data.push({
|
|
515
|
+
id: dep2.inputs[i],
|
|
516
|
+
prop: "loading_status",
|
|
517
|
+
value: { validation_error: message2.message }
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
if (validation_error_data.length > 0) {
|
|
521
|
+
update_value(validation_error_data);
|
|
522
|
+
loading_status.update({
|
|
523
|
+
status: "complete",
|
|
524
|
+
fn_index: message.fn_index,
|
|
525
|
+
eta: 0,
|
|
526
|
+
queue: false,
|
|
527
|
+
queue_position: null
|
|
528
|
+
});
|
|
529
|
+
set_status($loading_status);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
488
533
|
if (message.broken && !broken_connection) {
|
|
489
534
|
messages = [
|
|
490
535
|
new_message(
|
|
@@ -567,7 +612,7 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
|
|
|
567
612
|
submit_map.delete(dep_index);
|
|
568
613
|
}
|
|
569
614
|
if (status.stage === "error" && !broken_connection && !message.session_not_found) {
|
|
570
|
-
if (status.message) {
|
|
615
|
+
if (status.message && typeof status.message === "string") {
|
|
571
616
|
const _message = status.message.replace(
|
|
572
617
|
MESSAGE_QUOTE_RE,
|
|
573
618
|
(_2, b) => b
|
|
@@ -636,6 +681,11 @@ async function handle_mount() {
|
|
|
636
681
|
target.addEventListener("prop_change", (e) => {
|
|
637
682
|
if (!isCustomEvent(e)) throw new Error("not a custom event");
|
|
638
683
|
const { id, prop, value } = e.detail;
|
|
684
|
+
if (prop === "value") {
|
|
685
|
+
update_value([
|
|
686
|
+
{ id, prop: "loading_status", value: { validation_error: void 0 } }
|
|
687
|
+
]);
|
|
688
|
+
}
|
|
639
689
|
update_value([{ id, prop, value }]);
|
|
640
690
|
if (prop === "input_ready" && value === false) {
|
|
641
691
|
inputs_waiting.push(id);
|
|
@@ -780,6 +830,37 @@ function screen_recording() {
|
|
|
780
830
|
screen_recorder.startRecording();
|
|
781
831
|
}
|
|
782
832
|
}
|
|
833
|
+
let footer_height = 0;
|
|
834
|
+
let root_container;
|
|
835
|
+
$: root_node = $_layout && get_root_node(root_container);
|
|
836
|
+
function get_root_node(container) {
|
|
837
|
+
if (!container) return null;
|
|
838
|
+
return container.children[container.children.length - 1];
|
|
839
|
+
}
|
|
840
|
+
function handle_resize() {
|
|
841
|
+
if ("parentIFrame" in window) {
|
|
842
|
+
const box = root_node?.getBoundingClientRect();
|
|
843
|
+
if (!box) return;
|
|
844
|
+
window.parentIFrame?.size(box.bottom + footer_height + 32);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
onMount(() => {
|
|
848
|
+
if ("parentIFrame" in window) {
|
|
849
|
+
window.parentIFrame?.autoResize(false);
|
|
850
|
+
}
|
|
851
|
+
const mut = new MutationObserver(handle_resize);
|
|
852
|
+
const res = new ResizeObserver(handle_resize);
|
|
853
|
+
mut.observe(root_container, {
|
|
854
|
+
childList: true,
|
|
855
|
+
subtree: true,
|
|
856
|
+
attributes: true
|
|
857
|
+
});
|
|
858
|
+
res.observe(root_container);
|
|
859
|
+
return () => {
|
|
860
|
+
mut.disconnect();
|
|
861
|
+
res.disconnect();
|
|
862
|
+
};
|
|
863
|
+
});
|
|
783
864
|
</script>
|
|
784
865
|
|
|
785
866
|
<svelte:head>
|
|
@@ -795,6 +876,7 @@ function screen_recording() {
|
|
|
795
876
|
<div
|
|
796
877
|
class="contain"
|
|
797
878
|
style:flex-grow={app_mode ? "1" : "auto"}
|
|
879
|
+
bind:this={root_container}
|
|
798
880
|
style:margin-right={vibe_mode ? `${vibe_editor_width}px` : "0"}
|
|
799
881
|
>
|
|
800
882
|
{#if $_layout && app.config}
|
|
@@ -813,7 +895,7 @@ function screen_recording() {
|
|
|
813
895
|
</div>
|
|
814
896
|
|
|
815
897
|
{#if show_footer}
|
|
816
|
-
<footer>
|
|
898
|
+
<footer bind:clientHeight={footer_height}>
|
|
817
899
|
{#if show_api}
|
|
818
900
|
<button
|
|
819
901
|
on:click={() => {
|
package/dist/src/Embed.svelte
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<script>import { getContext } from "svelte";
|
|
1
|
+
<script>import { getContext, onMount } from "svelte";
|
|
2
2
|
import space_logo from "./images/spaces.svg";
|
|
3
3
|
import { _ } from "svelte-i18n";
|
|
4
|
+
import { navbar_config } from "./navbar_store";
|
|
4
5
|
export let wrapper;
|
|
5
6
|
export let version;
|
|
6
7
|
export let initial_height;
|
|
7
8
|
export let fill_width;
|
|
8
9
|
export let is_embed;
|
|
9
|
-
export let is_lite;
|
|
10
10
|
export let space;
|
|
11
11
|
export let display;
|
|
12
12
|
export let info;
|
|
@@ -14,7 +14,45 @@ export let loaded;
|
|
|
14
14
|
export let pages = [];
|
|
15
15
|
export let current_page = "";
|
|
16
16
|
export let root;
|
|
17
|
-
|
|
17
|
+
export let components = [];
|
|
18
|
+
let navbar_component = components.find((c) => c.type === "navbar");
|
|
19
|
+
let navbar = navbar_component ? {
|
|
20
|
+
visible: navbar_component.props.visible,
|
|
21
|
+
main_page_name: navbar_component.props.main_page_name,
|
|
22
|
+
value: navbar_component.props.value
|
|
23
|
+
} : null;
|
|
24
|
+
if (navbar) {
|
|
25
|
+
navbar_config.set(navbar);
|
|
26
|
+
}
|
|
27
|
+
$: if ($navbar_config) {
|
|
28
|
+
navbar = {
|
|
29
|
+
visible: $navbar_config.visible ?? true,
|
|
30
|
+
main_page_name: $navbar_config.main_page_name ?? "Home",
|
|
31
|
+
value: $navbar_config.value ?? null
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
$: show_navbar = pages.length > 1 && (navbar === null || navbar.visible !== false);
|
|
35
|
+
$: effective_pages = (() => {
|
|
36
|
+
let visible_pages = pages.filter(([route, label, show], index) => {
|
|
37
|
+
if (index === 0 && route === "") {
|
|
38
|
+
return navbar?.main_page_name !== false;
|
|
39
|
+
}
|
|
40
|
+
return show !== false;
|
|
41
|
+
});
|
|
42
|
+
let base_pages = navbar && navbar.main_page_name !== false && navbar.main_page_name !== "Home" ? visible_pages.map(
|
|
43
|
+
([route, label, show], index) => index === 0 && route === "" && label === "Home" ? [route, navbar.main_page_name] : [route, label]
|
|
44
|
+
) : visible_pages.map(
|
|
45
|
+
([route, label]) => [route, label]
|
|
46
|
+
);
|
|
47
|
+
if (navbar?.value && navbar.value.length > 0) {
|
|
48
|
+
const existing_routes = new Set(base_pages.map(([route]) => route));
|
|
49
|
+
const additional_pages = navbar.value.map(
|
|
50
|
+
([page_name, page_path]) => [page_path, page_name]
|
|
51
|
+
).filter(([route]) => !existing_routes.has(route));
|
|
52
|
+
return [...base_pages, ...additional_pages];
|
|
53
|
+
}
|
|
54
|
+
return base_pages;
|
|
55
|
+
})();
|
|
18
56
|
</script>
|
|
19
57
|
|
|
20
58
|
<div
|
|
@@ -27,27 +65,24 @@ const set_page = getContext("set_lite_page");
|
|
|
27
65
|
style:flex-grow={!display ? "1" : "auto"}
|
|
28
66
|
data-iframe-height
|
|
29
67
|
>
|
|
30
|
-
{#if
|
|
68
|
+
{#if show_navbar}
|
|
31
69
|
<div class="nav-holder">
|
|
32
70
|
<nav class="fillable" class:fill_width>
|
|
33
|
-
{#each
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
>{label}
|
|
49
|
-
</a>
|
|
50
|
-
{/if}
|
|
71
|
+
{#each effective_pages as [route, label], i}
|
|
72
|
+
<a
|
|
73
|
+
href={route.startsWith("http://") || route.startsWith("https://")
|
|
74
|
+
? route
|
|
75
|
+
: `${root}/${route}`}
|
|
76
|
+
class:active={route === current_page}
|
|
77
|
+
data-sveltekit-reload
|
|
78
|
+
target={route.startsWith("http://") || route.startsWith("https://")
|
|
79
|
+
? "_blank"
|
|
80
|
+
: "_self"}
|
|
81
|
+
rel={route.startsWith("http://") || route.startsWith("https://")
|
|
82
|
+
? "noopener noreferrer"
|
|
83
|
+
: ""}
|
|
84
|
+
>{label}
|
|
85
|
+
</a>
|
|
51
86
|
{/each}
|
|
52
87
|
</nav>
|
|
53
88
|
</div>
|
|
@@ -93,16 +128,14 @@ const set_page = getContext("set_lite_page");
|
|
|
93
128
|
margin: 0 auto;
|
|
94
129
|
padding: 0 var(--size-8);
|
|
95
130
|
}
|
|
96
|
-
nav a
|
|
97
|
-
button {
|
|
131
|
+
nav a {
|
|
98
132
|
padding: var(--size-1) var(--size-2);
|
|
99
133
|
border-radius: var(--block-radius);
|
|
100
134
|
border-width: var(--block-border-width);
|
|
101
135
|
border-color: transparent;
|
|
102
136
|
color: var(--body-text-color-subdued);
|
|
103
137
|
}
|
|
104
|
-
nav a.active
|
|
105
|
-
button.active {
|
|
138
|
+
nav a.active {
|
|
106
139
|
color: var(--body-text-color);
|
|
107
140
|
border-color: var(--block-border-color);
|
|
108
141
|
background-color: var(--block-background-fill);
|
|
@@ -6,14 +6,14 @@ declare const __propDef: {
|
|
|
6
6
|
initial_height: string;
|
|
7
7
|
fill_width: boolean;
|
|
8
8
|
is_embed: boolean;
|
|
9
|
-
is_lite: boolean;
|
|
10
9
|
space: string | null;
|
|
11
10
|
display: boolean;
|
|
12
11
|
info: boolean;
|
|
13
12
|
loaded: boolean;
|
|
14
|
-
pages?: [string, string][];
|
|
13
|
+
pages?: [string, string, boolean][];
|
|
15
14
|
current_page?: string;
|
|
16
15
|
root: string;
|
|
16
|
+
components?: any[];
|
|
17
17
|
};
|
|
18
18
|
events: {
|
|
19
19
|
[evt: string]: CustomEvent<any>;
|
package/dist/src/Render.svelte
CHANGED
|
@@ -39,10 +39,14 @@ $: {
|
|
|
39
39
|
setContext("BLOCK_KEY", parent);
|
|
40
40
|
$: {
|
|
41
41
|
if (node && node.type === "form") {
|
|
42
|
-
|
|
43
|
-
(c) =>
|
|
44
|
-
)
|
|
45
|
-
|
|
42
|
+
const allChildrenInvisible = node.children?.every(
|
|
43
|
+
(c) => c.props.visible === false || c.props.visible === "hidden"
|
|
44
|
+
);
|
|
45
|
+
if (allChildrenInvisible) {
|
|
46
|
+
const hasHiddenChild = node.children?.some(
|
|
47
|
+
(c) => c.props.visible === "hidden"
|
|
48
|
+
);
|
|
49
|
+
node.props.visible = hasHiddenChild ? "hidden" : false;
|
|
46
50
|
} else {
|
|
47
51
|
node.props.visible = true;
|
|
48
52
|
}
|
|
@@ -76,7 +80,8 @@ $: node.props.gradio = new Gradio(
|
|
|
76
80
|
{...node.props}
|
|
77
81
|
{theme_mode}
|
|
78
82
|
{root}
|
|
79
|
-
visible={typeof node.props.visible === "boolean"
|
|
83
|
+
visible={typeof node.props.visible === "boolean" ||
|
|
84
|
+
node.props.visible === "hidden"
|
|
80
85
|
? node.props.visible
|
|
81
86
|
: true}
|
|
82
87
|
>
|
|
@@ -43,13 +43,13 @@ $: normalised_root = root.replace(/\/$/, "");
|
|
|
43
43
|
class="highlight">import</span
|
|
44
44
|
> Client{#if has_file_path}, handle_file{/if}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
client = Client(<span class="token string">"{space_id || root}"</span
|
|
47
47
|
>{#if username !== null}, auth=("{username}", **password**){/if})
|
|
48
|
-
|
|
48
|
+
result = client.<span class="highlight">predict</span
|
|
49
49
|
>(<!--
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
-->{#each endpoint_parameters as { python_type, example_input, parameter_name, parameter_has_default, parameter_default }, i}<!--
|
|
51
|
+
-->
|
|
52
|
+
{parameter_name
|
|
53
53
|
? parameter_name + "="
|
|
54
54
|
: ""}<span
|
|
55
55
|
>{represent_value(
|
|
@@ -59,11 +59,11 @@ $: normalised_root = root.replace(/\/$/, "");
|
|
|
59
59
|
)}</span
|
|
60
60
|
>,{/each}<!--
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
-->
|
|
63
|
+
api_name=<span class="api-name">"/{dependency.api_name}"</span><!--
|
|
64
|
+
-->
|
|
65
|
+
)
|
|
66
|
+
<span class="highlight">print</span>(result)</pre>
|
|
67
67
|
</div>
|
|
68
68
|
</code>
|
|
69
69
|
</Block>
|
package/dist/src/i18n.d.ts
CHANGED
|
@@ -15,11 +15,12 @@ export interface LangsRecord {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
export declare function is_translation_metadata(obj: any): obj is I18nData;
|
|
18
|
+
export declare const i18n_marker = "__i18n__";
|
|
18
19
|
export declare function translate_if_needed(value: any): string;
|
|
19
20
|
export declare function process_langs(): LangsRecord;
|
|
20
21
|
export declare const language_choices: [string, string][];
|
|
21
22
|
export declare let all_common_keys: Set<string>;
|
|
22
|
-
export declare function setupi18n(custom_translations?: Record<string, Record<string, string
|
|
23
|
+
export declare function setupi18n(custom_translations?: Record<string, Record<string, string>>, preferred_locale?: string): Promise<void>;
|
|
23
24
|
export declare function changeLocale(new_locale: string): void;
|
|
24
25
|
export declare function get_initial_locale(browser_locale: string | null, available_locales: string[], fallback_locale?: string): string;
|
|
25
26
|
export declare function load_translations(translations: {
|
package/dist/src/i18n.js
CHANGED
|
@@ -43,12 +43,12 @@ export function is_translation_metadata(obj) {
|
|
|
43
43
|
typeof obj.key === "string";
|
|
44
44
|
return result;
|
|
45
45
|
}
|
|
46
|
+
export const i18n_marker = "__i18n__";
|
|
46
47
|
// handles strings with embedded JSON metadata of shape "__i18n__{"key": "some.key"}"
|
|
47
48
|
export function translate_if_needed(value) {
|
|
48
49
|
if (typeof value !== "string") {
|
|
49
50
|
return value;
|
|
50
51
|
}
|
|
51
|
-
const i18n_marker = "__i18n__";
|
|
52
52
|
const marker_index = value.indexOf(i18n_marker);
|
|
53
53
|
if (marker_index === -1) {
|
|
54
54
|
return value;
|
|
@@ -108,7 +108,19 @@ export const language_choices = Object.entries(processed_langs).map(([code]) =>
|
|
|
108
108
|
export let all_common_keys = new Set();
|
|
109
109
|
let i18n_initialized = false;
|
|
110
110
|
let previous_translations;
|
|
111
|
-
|
|
111
|
+
function get_lang_from_preferred_locale(header) {
|
|
112
|
+
const options = header
|
|
113
|
+
.split(",")
|
|
114
|
+
.map((value) => value.includes(";") ? value.split(";").slice(0, 2) : [value, 1]);
|
|
115
|
+
options.sort((a, b) => parseFloat(b[1]) - parseFloat(a[1]));
|
|
116
|
+
for (const [lang, _] of options) {
|
|
117
|
+
if (available_locales.includes(lang)) {
|
|
118
|
+
return lang;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
export async function setupi18n(custom_translations, preferred_locale) {
|
|
112
124
|
const should_reinitialize = i18n_initialized && custom_translations !== previous_translations;
|
|
113
125
|
if (i18n_initialized && !should_reinitialize) {
|
|
114
126
|
return;
|
|
@@ -118,10 +130,17 @@ export async function setupi18n(custom_translations) {
|
|
|
118
130
|
processed_langs,
|
|
119
131
|
custom_translations: custom_translations ?? {}
|
|
120
132
|
});
|
|
133
|
+
let initial_locale = null;
|
|
121
134
|
const browser_locale = getLocaleFromNavigator();
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
135
|
+
if (preferred_locale) {
|
|
136
|
+
initial_locale = get_lang_from_preferred_locale(preferred_locale);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
initial_locale =
|
|
140
|
+
browser_locale && available_locales.includes(browser_locale)
|
|
141
|
+
? browser_locale
|
|
142
|
+
: null;
|
|
143
|
+
}
|
|
125
144
|
if (!initial_locale) {
|
|
126
145
|
const normalized_locale = browser_locale?.split("-")[0];
|
|
127
146
|
initial_locale =
|