@gradio/core 0.20.0 → 0.22.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 CHANGED
@@ -1,5 +1,38 @@
1
1
  # @gradio/core
2
2
 
3
+ ## 0.22.0
4
+
5
+ ### Features
6
+
7
+ - [#11572](https://github.com/gradio-app/gradio/pull/11572) [`552a5eb`](https://github.com/gradio-app/gradio/commit/552a5ebf9beb5d543f82a24a546daaf9ad3d88b1) - handle i18n error when browsers aren't set to en. Thanks @hannahblair!
8
+
9
+ ## 0.21.0
10
+
11
+ ### Features
12
+
13
+ - [#11427](https://github.com/gradio-app/gradio/pull/11427) [`6b2bcd0`](https://github.com/gradio-app/gradio/commit/6b2bcd097ae5ef999a7fb273ecf7c7e4c0eab305) - Improve load times of the Gradio front-end. Thanks @pngwn!
14
+ - [#11511](https://github.com/gradio-app/gradio/pull/11511) [`1a99336`](https://github.com/gradio-app/gradio/commit/1a99336043076e7b0a4c4b07f97082f0361882f4) - Fix SSR. Thanks @pngwn!
15
+
16
+ ### Dependency updates
17
+
18
+ - @gradio/atoms@0.16.3
19
+ - @gradio/statustracker@0.10.14
20
+ - @gradio/column@0.2.1
21
+ - @gradio/tabs@0.4.5
22
+ - @gradio/upload@0.16.10
23
+ - @gradio/video@0.14.20
24
+ - @gradio/tabitem@0.5.0
25
+ - @gradio/code@0.14.10
26
+ - @gradio/paramviewer@0.7.12
27
+ - @gradio/client@1.15.5
28
+ - @gradio/image@0.22.12
29
+ - @gradio/button@0.5.6
30
+ - @gradio/checkbox@0.4.25
31
+ - @gradio/gallery@0.15.26
32
+ - @gradio/plot@0.9.19
33
+ - @gradio/textbox@0.10.16
34
+ - @gradio/file@0.12.23
35
+
3
36
  ## 0.20.0
4
37
 
5
38
  ### Features
@@ -3,7 +3,6 @@ import { _ } from "svelte-i18n";
3
3
  import { Client } from "@gradio/client";
4
4
  import { writable } from "svelte/store";
5
5
  import { setupi18n } from "./i18n";
6
- import { ApiDocs, ApiRecorder, Settings } from "./api_docs/";
7
6
  import { Toast } from "@gradio/statustracker";
8
7
  import MountComponents from "./MountComponents.svelte";
9
8
  import { prefix_css } from "./css";
@@ -61,6 +60,7 @@ $:
61
60
  old_dependencies = dependencies;
62
61
  }
63
62
  async function run() {
63
+ await setupi18n(app.config?.i18n_translations || void 0);
64
64
  layout_creating = true;
65
65
  await create_layout({
66
66
  components,
@@ -80,8 +80,36 @@ let settings_visible = search_params.get("view") === "settings";
80
80
  let api_recorder_visible = search_params.get("view") === "api-recorder" && show_api;
81
81
  let allow_zoom = true;
82
82
  let allow_video_trim = true;
83
- function set_api_docs_visible(visible) {
83
+ let ApiDocs = null;
84
+ let ApiRecorder = null;
85
+ let Settings = null;
86
+ async function loadApiDocs() {
87
+ if (!ApiDocs || !ApiRecorder) {
88
+ const api_docs_module = await import("./api_docs/ApiDocs.svelte");
89
+ const api_recorder_module = await import("./api_docs/ApiRecorder.svelte");
90
+ if (!ApiDocs)
91
+ ApiDocs = api_docs_module.default;
92
+ if (!ApiRecorder)
93
+ ApiRecorder = api_recorder_module.default;
94
+ }
95
+ }
96
+ async function loadApiRecorder() {
97
+ if (!ApiRecorder) {
98
+ const api_recorder_module = await import("./api_docs/ApiRecorder.svelte");
99
+ ApiRecorder = api_recorder_module.default;
100
+ }
101
+ }
102
+ async function loadSettings() {
103
+ if (!Settings) {
104
+ const settings_module = await import("./api_docs/Settings.svelte");
105
+ Settings = settings_module.default;
106
+ }
107
+ }
108
+ async function set_api_docs_visible(visible) {
84
109
  api_recorder_visible = false;
110
+ if (visible) {
111
+ await loadApiDocs();
112
+ }
85
113
  api_docs_visible = visible;
86
114
  let params = new URLSearchParams(window.location.search);
87
115
  if (visible) {
@@ -91,7 +119,10 @@ function set_api_docs_visible(visible) {
91
119
  }
92
120
  history.replaceState(null, "", "?" + params.toString());
93
121
  }
94
- function set_settings_visible(visible) {
122
+ async function set_settings_visible(visible) {
123
+ if (visible) {
124
+ await loadSettings();
125
+ }
95
126
  let params = new URLSearchParams(window.location.search);
96
127
  if (visible) {
97
128
  params.set("view", "settings");
@@ -658,6 +689,15 @@ onMount(() => {
658
689
  $is_screen_recording = isRecording;
659
690
  }
660
691
  );
692
+ if (api_docs_visible) {
693
+ loadApiDocs();
694
+ }
695
+ if (api_recorder_visible) {
696
+ loadApiRecorder();
697
+ }
698
+ if (settings_visible) {
699
+ loadSettings();
700
+ }
661
701
  });
662
702
  function screen_recording() {
663
703
  if ($is_screen_recording) {
@@ -666,10 +706,6 @@ function screen_recording() {
666
706
  screen_recorder.startRecording();
667
707
  }
668
708
  }
669
- let i18n_ready = false;
670
- setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
671
- i18n_ready = true;
672
- });
673
709
  </script>
674
710
 
675
711
  <svelte:head>
@@ -683,7 +719,7 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
683
719
 
684
720
  <div class="wrap" style:min-height={app_mode ? "100%" : "auto"}>
685
721
  <div class="contain" style:flex-grow={app_mode ? "1" : "auto"}>
686
- {#if $_layout && app.config && i18n_ready}
722
+ {#if $_layout && app.config}
687
723
  <MountComponents
688
724
  rootNode={$_layout}
689
725
  {root}
@@ -705,6 +741,10 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
705
741
  on:click={() => {
706
742
  set_api_docs_visible(!api_docs_visible);
707
743
  }}
744
+ on:mouseenter={() => {
745
+ loadApiDocs();
746
+ loadApiRecorder();
747
+ }}
708
748
  class="show-api"
709
749
  >
710
750
  {#if app.config?.mcp_server}
@@ -741,6 +781,9 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
741
781
  on:click={() => {
742
782
  set_settings_visible(!settings_visible);
743
783
  }}
784
+ on:mouseenter={() => {
785
+ loadSettings();
786
+ }}
744
787
  class="settings"
745
788
  >
746
789
  {$_("common.settings")}
@@ -750,7 +793,7 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
750
793
  {/if}
751
794
  </div>
752
795
 
753
- {#if api_recorder_visible}
796
+ {#if api_recorder_visible && ApiRecorder}
754
797
  <!-- TODO: fix -->
755
798
  <!-- svelte-ignore a11y-click-events-have-key-events-->
756
799
  <!-- svelte-ignore a11y-no-static-element-interactions-->
@@ -761,11 +804,11 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
761
804
  api_recorder_visible = false;
762
805
  }}
763
806
  >
764
- <ApiRecorder {api_calls} {dependencies} />
807
+ <svelte:component this={ApiRecorder} {api_calls} {dependencies} />
765
808
  </div>
766
809
  {/if}
767
810
 
768
- {#if api_docs_visible && $_layout}
811
+ {#if api_docs_visible && $_layout && ApiDocs}
769
812
  <div class="api-docs">
770
813
  <!-- TODO: fix -->
771
814
  <!-- svelte-ignore a11y-click-events-have-key-events-->
@@ -777,12 +820,14 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
777
820
  }}
778
821
  />
779
822
  <div class="api-docs-wrap">
780
- <ApiDocs
823
+ <svelte:component
824
+ this={ApiDocs}
781
825
  root_node={$_layout}
782
826
  on:close={(event) => {
783
827
  set_api_docs_visible(false);
784
828
  api_calls = [];
785
- api_recorder_visible = event.detail?.api_recorder_visible;
829
+ api_recorder_visible = api_recorder_visible =
830
+ event.detail?.api_recorder_visible;
786
831
  }}
787
832
  {dependencies}
788
833
  {root}
@@ -795,7 +840,7 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
795
840
  </div>
796
841
  {/if}
797
842
 
798
- {#if settings_visible && $_layout && app.config}
843
+ {#if settings_visible && $_layout && app.config && Settings}
799
844
  <div class="api-docs">
800
845
  <!-- TODO: fix -->
801
846
  <!-- svelte-ignore a11y-click-events-have-key-events-->
@@ -807,13 +852,14 @@ setupi18n(app.config?.i18n_translations ?? void 0).then(() => {
807
852
  }}
808
853
  />
809
854
  <div class="api-docs-wrap">
810
- <Settings
855
+ <svelte:component
856
+ this={Settings}
811
857
  bind:allow_zoom
812
858
  bind:allow_video_trim
813
- on:close={(event) => {
859
+ on:close={() => {
814
860
  set_settings_visible(false);
815
861
  }}
816
- on:start_recording={(event) => {
862
+ on:start_recording={() => {
817
863
  screen_recording();
818
864
  }}
819
865
  pwa_enabled={app.config.pwa}
@@ -39,7 +39,9 @@ $: {
39
39
  setContext("BLOCK_KEY", parent);
40
40
  $: {
41
41
  if (node && node.type === "form") {
42
- if (node.children?.every((c) => !c.props.visible)) {
42
+ if (node.children?.every(
43
+ (c) => typeof c.props.visible === "boolean" && !c.props.visible
44
+ )) {
43
45
  node.props.visible = false;
44
46
  } else {
45
47
  node.props.visible = true;
@@ -61,34 +63,39 @@ $:
61
63
  );
62
64
  </script>
63
65
 
64
- <RenderComponent
65
- _id={node?.id}
66
- component={node.component}
67
- bind:instance={node.instance}
68
- bind:value={node.props.value}
69
- elem_id={("elem_id" in node.props && node.props.elem_id) ||
70
- `component-${node.id}`}
71
- elem_classes={("elem_classes" in node.props && node.props.elem_classes) || []}
72
- {target}
73
- {...node.props}
74
- {theme_mode}
75
- {root}
76
- visible={typeof node.props.visible === "boolean" ? node.props.visible : true}
77
- >
78
- {#if node.children && node.children.length}
79
- {#each node.children as _node (_node.id)}
80
- <svelte:self
81
- node={_node}
82
- component={_node.component}
83
- {target}
84
- id={_node.id}
85
- {root}
86
- {theme_mode}
87
- on:destroy
88
- on:mount
89
- {max_file_size}
90
- {client}
91
- />
92
- {/each}
93
- {/if}
94
- </RenderComponent>
66
+ {#if node.component}
67
+ <RenderComponent
68
+ _id={node?.id}
69
+ component={node.component}
70
+ bind:instance={node.instance}
71
+ bind:value={node.props.value}
72
+ elem_id={("elem_id" in node.props && node.props.elem_id) ||
73
+ `component-${node.id}`}
74
+ elem_classes={("elem_classes" in node.props && node.props.elem_classes) ||
75
+ []}
76
+ {target}
77
+ {...node.props}
78
+ {theme_mode}
79
+ {root}
80
+ visible={typeof node.props.visible === "boolean"
81
+ ? node.props.visible
82
+ : true}
83
+ >
84
+ {#if node.children && node.children.length}
85
+ {#each node.children as _node (_node.id)}
86
+ <svelte:self
87
+ node={_node}
88
+ component={_node.component}
89
+ {target}
90
+ id={_node.id}
91
+ {root}
92
+ {theme_mode}
93
+ on:destroy
94
+ on:mount
95
+ {max_file_size}
96
+ {client}
97
+ />
98
+ {/each}
99
+ {/if}
100
+ </RenderComponent>
101
+ {/if}
@@ -34,7 +34,7 @@ function wrap(component2) {
34
34
  });
35
35
  return ProxiedMyClass;
36
36
  }
37
- const _component = wrap(component);
37
+ let _component = wrap(component);
38
38
  const supported_props = [
39
39
  "description",
40
40
  "info",
@@ -56,20 +56,19 @@ $:
56
56
  value = translate_if_needed(value);
57
57
  </script>
58
58
 
59
- <!-- {#if visible} -->
60
- <svelte:component
61
- this={_component}
62
- bind:this={instance}
63
- bind:value
64
- on:prop_change
65
- {elem_id}
66
- {elem_classes}
67
- {target}
68
- {visible}
69
- {...$$restProps}
70
- {theme_mode}
71
- {root}
72
- >
73
- <slot />
74
- </svelte:component>
75
- <!-- {/if} -->
59
+ {#if visible}
60
+ <svelte:component
61
+ this={_component}
62
+ bind:this={instance}
63
+ bind:value
64
+ on:prop_change
65
+ {elem_id}
66
+ {elem_classes}
67
+ {target}
68
+ {...$$restProps}
69
+ {theme_mode}
70
+ {root}
71
+ >
72
+ <slot />
73
+ </svelte:component>
74
+ {/if}
@@ -2,8 +2,17 @@ export interface I18nData {
2
2
  __type__: "translation_metadata";
3
3
  key: string;
4
4
  }
5
+ export type Lang = {
6
+ [key: string]: Record<string, string> | string;
7
+ };
5
8
  export interface LangsRecord {
6
- [lang: string]: any;
9
+ [lang: string]: {
10
+ type: "lazy";
11
+ data: () => Promise<Lang>;
12
+ } | {
13
+ type: "static";
14
+ data: Lang;
15
+ };
7
16
  }
8
17
  export declare function is_translation_metadata(obj: any): obj is I18nData;
9
18
  export declare function translate_if_needed(value: any): string;
@@ -13,4 +22,7 @@ export declare let all_common_keys: Set<string>;
13
22
  export declare function setupi18n(custom_translations?: Record<string, Record<string, string>>): Promise<void>;
14
23
  export declare function changeLocale(new_locale: string): void;
15
24
  export declare function get_initial_locale(browser_locale: string | null, available_locales: string[], fallback_locale?: string): string;
16
- export declare function load_translations(translations: LangsRecord | null | undefined): void;
25
+ export declare function load_translations(translations: {
26
+ processed_langs: LangsRecord;
27
+ custom_translations: Record<string, Record<string, string>>;
28
+ }): void;
package/dist/src/i18n.js CHANGED
@@ -1,10 +1,41 @@
1
- import { addMessages, init, getLocaleFromNavigator, locale } from "svelte-i18n";
1
+ import { addMessages, init, getLocaleFromNavigator, locale, register, waitLocale } from "svelte-i18n";
2
2
  import { formatter } from "./gradio_helper";
3
- const langs = import.meta.glob("./lang/*.json", {
4
- eager: true
5
- });
3
+ const lang_map = {
4
+ ar: "العربية",
5
+ ca: "Català",
6
+ ckb: "کوردی",
7
+ de: "Deutsch",
8
+ en: "English",
9
+ es: "Español",
10
+ eu: "Euskara",
11
+ fa: "فارسی",
12
+ fi: "Suomi",
13
+ fr: "Français",
14
+ he: "עברית",
15
+ hi: "हिंदी",
16
+ ja: "日本語",
17
+ ko: "한국어",
18
+ lt: "Lietuvių",
19
+ nb: "Norsk bokmål",
20
+ nl: "Nederlands",
21
+ pl: "Polski",
22
+ "pt-BR": "Português do Brasil",
23
+ pt: "Português",
24
+ ro: "Română",
25
+ ru: "Русский",
26
+ sv: "Svenska",
27
+ ta: "தமிழ்",
28
+ th: "ภาษาไทย",
29
+ tr: "Türkçe",
30
+ uk: "Українська",
31
+ ur: "اردو",
32
+ uz: "O'zbek",
33
+ "zh-CN": "简体中文",
34
+ "zh-TW": "繁體中文"
35
+ };
36
+ const langs = import.meta.glob("./lang/*.json");
37
+ import en from "./lang/en.json";
6
38
  export function is_translation_metadata(obj) {
7
- console.log(obj);
8
39
  const result = obj &&
9
40
  typeof obj === "object" &&
10
41
  obj.__type__ === "translation_metadata" &&
@@ -61,14 +92,18 @@ export function translate_if_needed(value) {
61
92
  }
62
93
  }
63
94
  export function process_langs() {
64
- return Object.fromEntries(Object.entries(langs).map(([path, module]) => [
95
+ const lazy_langs = Object.fromEntries(Object.entries(langs).map(([path, mod]) => [
65
96
  path.split("/").pop().split(".")[0],
66
- module.default
97
+ { type: "lazy", data: mod }
67
98
  ]));
99
+ return {
100
+ ...lazy_langs,
101
+ en: { type: "static", data: en }
102
+ };
68
103
  }
69
104
  const processed_langs = process_langs();
70
105
  const available_locales = Object.keys(processed_langs);
71
- export const language_choices = Object.entries(processed_langs).map(([code, data]) => [data._name || code, code]);
106
+ export const language_choices = Object.entries(processed_langs).map(([code]) => [lang_map[code] || code, code]);
72
107
  export let all_common_keys = new Set();
73
108
  let i18n_initialized = false;
74
109
  let previous_translations;
@@ -79,8 +114,8 @@ export async function setupi18n(custom_translations) {
79
114
  }
80
115
  previous_translations = custom_translations;
81
116
  load_translations({
82
- ...processed_langs,
83
- ...(custom_translations ?? {})
117
+ processed_langs,
118
+ custom_translations: custom_translations ?? {}
84
119
  });
85
120
  const browser_locale = getLocaleFromNavigator();
86
121
  let initial_locale = browser_locale && available_locales.includes(browser_locale)
@@ -97,17 +132,6 @@ export async function setupi18n(custom_translations) {
97
132
  fallbackLocale: "en",
98
133
  initialLocale: initial_locale
99
134
  });
100
- for (const lang_code in processed_langs) {
101
- if (processed_langs[lang_code] &&
102
- typeof processed_langs[lang_code] === "object" &&
103
- processed_langs[lang_code].common &&
104
- typeof processed_langs[lang_code].common === "object") {
105
- const common_ns = processed_langs[lang_code].common;
106
- for (const key in common_ns) {
107
- all_common_keys.add(`common.${key}`);
108
- }
109
- }
110
- }
111
135
  i18n_initialized = true;
112
136
  }
113
137
  export function changeLocale(new_locale) {
@@ -126,8 +150,17 @@ export function load_translations(translations) {
126
150
  return;
127
151
  }
128
152
  try {
129
- for (const lang in translations) {
130
- addMessages(lang, translations[lang]);
153
+ for (const lang in translations.custom_translations) {
154
+ addMessages(lang, translations.custom_translations[lang]);
155
+ }
156
+ for (const lang in translations.processed_langs) {
157
+ if (lang === "en" &&
158
+ translations.processed_langs[lang].type === "static") {
159
+ addMessages(lang, en);
160
+ }
161
+ else if (translations.processed_langs[lang].type === "lazy") {
162
+ register(lang, translations.processed_langs[lang].data);
163
+ }
131
164
  }
132
165
  }
133
166
  catch (e) {
@@ -97,7 +97,15 @@ export declare function get_component(type: string, class_id: string, root: stri
97
97
  example_components?: Map<ComponentMeta["type"], LoadingComponent>;
98
98
  };
99
99
  /**
100
- * Preload all components
100
+ * Preload only visible components
101
+ * @param components A list of component metadata
102
+ * @param layout The layout tree to determine visibility
103
+ * @param root The root url of the app
104
+ * @returns A map of component ids to their constructors
105
+ */
106
+ export declare function preload_visible_components(components: ComponentMeta[], layout: LayoutNode, root: string): Map<ComponentMeta["type"], LoadingComponent>;
107
+ /**
108
+ * Preload all components (legacy function, kept for backwards compatibility)
101
109
  * @param components A list of component metadata
102
110
  * @param root The root url of the app
103
111
  * @returns A map of component ids to their constructors