@gradio/core 0.0.2

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.
Files changed (87) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +201 -0
  3. package/blocks.ts +1 -0
  4. package/index.ts +4 -0
  5. package/login.ts +1 -0
  6. package/package.json +83 -0
  7. package/public/favicon.png +0 -0
  8. package/public/static/img/Bunny.obj +7474 -0
  9. package/public/static/img/Duck.glb +0 -0
  10. package/public/static/img/api-logo.svg +4 -0
  11. package/public/static/img/camera.svg +1 -0
  12. package/public/static/img/clear.svg +67 -0
  13. package/public/static/img/edit.svg +39 -0
  14. package/public/static/img/javascript.svg +16 -0
  15. package/public/static/img/logo.svg +19 -0
  16. package/public/static/img/logo_error.svg +134 -0
  17. package/public/static/img/python.svg +20 -0
  18. package/public/static/img/undo-solid.svg +1 -0
  19. package/src/Blocks.svelte +792 -0
  20. package/src/Embed.svelte +197 -0
  21. package/src/Login.stories.svelte +33 -0
  22. package/src/Login.svelte +111 -0
  23. package/src/MountComponents.svelte +30 -0
  24. package/src/Render.svelte +103 -0
  25. package/src/RenderComponent.svelte +67 -0
  26. package/src/api_docs/ApiBanner.svelte +118 -0
  27. package/src/api_docs/ApiDocs.svelte +418 -0
  28. package/src/api_docs/ApiRecorder.svelte +75 -0
  29. package/src/api_docs/CodeSnippet.svelte +198 -0
  30. package/src/api_docs/CopyButton.svelte +17 -0
  31. package/src/api_docs/EndpointDetail.svelte +37 -0
  32. package/src/api_docs/InputPayload.svelte +155 -0
  33. package/src/api_docs/InstallSnippet.svelte +59 -0
  34. package/src/api_docs/NoApi.svelte +74 -0
  35. package/src/api_docs/ParametersSnippet.svelte +106 -0
  36. package/src/api_docs/RecordingSnippet.svelte +224 -0
  37. package/src/api_docs/ResponseSnippet.svelte +97 -0
  38. package/src/api_docs/TryButton.svelte +19 -0
  39. package/src/api_docs/img/api-logo.svg +4 -0
  40. package/src/api_docs/img/bash.svg +8 -0
  41. package/src/api_docs/img/clear.svelte +19 -0
  42. package/src/api_docs/img/javascript.svg +16 -0
  43. package/src/api_docs/img/python.svg +20 -0
  44. package/src/api_docs/index.ts +2 -0
  45. package/src/api_docs/utils.ts +143 -0
  46. package/src/css.ts +116 -0
  47. package/src/gradio_helper.ts +7 -0
  48. package/src/i18n.test.ts +27 -0
  49. package/src/i18n.ts +36 -0
  50. package/src/images/lightning.svg +2 -0
  51. package/src/images/logo.svg +19 -0
  52. package/src/images/play.svg +2 -0
  53. package/src/images/spaces.svg +7 -0
  54. package/src/init.test.ts +521 -0
  55. package/src/init.ts +590 -0
  56. package/src/lang/BCP47_codes.js +58 -0
  57. package/src/lang/README.md +11 -0
  58. package/src/lang/ar.json +16 -0
  59. package/src/lang/ca.json +19 -0
  60. package/src/lang/ckb.json +108 -0
  61. package/src/lang/de.json +16 -0
  62. package/src/lang/en.json +118 -0
  63. package/src/lang/es.json +17 -0
  64. package/src/lang/eu.json +16 -0
  65. package/src/lang/fa.json +16 -0
  66. package/src/lang/fr.json +30 -0
  67. package/src/lang/he.json +16 -0
  68. package/src/lang/hi.json +16 -0
  69. package/src/lang/ja.json +16 -0
  70. package/src/lang/ko.json +16 -0
  71. package/src/lang/lt.json +16 -0
  72. package/src/lang/nl.json +16 -0
  73. package/src/lang/pl.json +16 -0
  74. package/src/lang/pt-BR.json +19 -0
  75. package/src/lang/ru.json +118 -0
  76. package/src/lang/ta.json +16 -0
  77. package/src/lang/tr.json +16 -0
  78. package/src/lang/uk.json +16 -0
  79. package/src/lang/ur.json +16 -0
  80. package/src/lang/uz.json +15 -0
  81. package/src/lang/zh-CN.json +115 -0
  82. package/src/lang/zh-TW.json +16 -0
  83. package/src/s-blocks.ts +1 -0
  84. package/src/s-login.ts +1 -0
  85. package/src/stores.ts +165 -0
  86. package/src/types.ts +106 -0
  87. package/src/vite-env-override.d.ts +20 -0
package/src/init.ts ADDED
@@ -0,0 +1,590 @@
1
+ import { writable, type Writable, get } from "svelte/store";
2
+ import type {
3
+ ComponentMeta,
4
+ Dependency,
5
+ LayoutNode,
6
+ TargetMap,
7
+ LoadingComponent
8
+ } from "./types";
9
+ import { load_component } from "virtual:component-loader";
10
+ import type { client_return } from "@gradio/client";
11
+ import { create_loading_status_store } from "./stores";
12
+ import { _ } from "svelte-i18n";
13
+
14
+ export interface UpdateTransaction {
15
+ id: number;
16
+ value: any;
17
+ prop: string;
18
+ }
19
+
20
+ let pending_updates: UpdateTransaction[][] = [];
21
+
22
+ /**
23
+ * Create a store with the layout and a map of targets
24
+ * @returns A store with the layout and a map of targets
25
+ */
26
+ export function create_components(): {
27
+ layout: Writable<ComponentMeta>;
28
+ targets: Writable<TargetMap>;
29
+ update_value: (updates: UpdateTransaction[]) => void;
30
+ get_data: (id: number) => any | Promise<any>;
31
+ loading_status: ReturnType<typeof create_loading_status_store>;
32
+ scheduled_updates: Writable<boolean>;
33
+ create_layout: (args: {
34
+ app: client_return;
35
+ components: ComponentMeta[];
36
+ layout: LayoutNode;
37
+ dependencies: Dependency[];
38
+ root: string;
39
+ options: {
40
+ fill_height: boolean;
41
+ };
42
+ }) => void;
43
+ rerender_layout: (args: {
44
+ render_id: number;
45
+ components: ComponentMeta[];
46
+ layout: LayoutNode;
47
+ root: string;
48
+ dependencies: Dependency[];
49
+ }) => void;
50
+ } {
51
+ let _component_map: Map<number, ComponentMeta>;
52
+
53
+ let target_map: Writable<TargetMap> = writable({});
54
+ let _target_map: TargetMap = {};
55
+ let inputs: Set<number>;
56
+ let outputs: Set<number>;
57
+ let constructor_map: Map<ComponentMeta["type"], LoadingComponent>;
58
+ let instance_map: { [id: number]: ComponentMeta };
59
+ let loading_status: ReturnType<typeof create_loading_status_store> =
60
+ create_loading_status_store();
61
+ const layout_store: Writable<ComponentMeta> = writable();
62
+ let _components: ComponentMeta[] = [];
63
+ let app: client_return;
64
+ let keyed_component_values: Record<string | number, any> = {};
65
+ let _rootNode: ComponentMeta;
66
+
67
+ function create_layout({
68
+ app: _app,
69
+ components,
70
+ layout,
71
+ dependencies,
72
+ root,
73
+ options
74
+ }: {
75
+ app: client_return;
76
+ components: ComponentMeta[];
77
+ layout: LayoutNode;
78
+ dependencies: Dependency[];
79
+ root: string;
80
+ options: {
81
+ fill_height: boolean;
82
+ };
83
+ }): void {
84
+ app = _app;
85
+ store_keyed_values(_components);
86
+
87
+ _components = components;
88
+ inputs = new Set();
89
+ outputs = new Set();
90
+ pending_updates = [];
91
+ constructor_map = new Map();
92
+ _component_map = new Map();
93
+
94
+ instance_map = {};
95
+
96
+ _rootNode = {
97
+ id: layout.id,
98
+ type: "column",
99
+ props: { interactive: false, scale: options.fill_height ? 1 : null },
100
+ has_modes: false,
101
+ instance: null as unknown as ComponentMeta["instance"],
102
+ component: null as unknown as ComponentMeta["component"],
103
+ component_class_id: "",
104
+ key: null
105
+ };
106
+
107
+ components.push(_rootNode);
108
+
109
+ dependencies.forEach((dep) => {
110
+ loading_status.register(dep.id, dep.inputs, dep.outputs);
111
+ dep.frontend_fn = process_frontend_fn(
112
+ dep.js,
113
+ !!dep.backend_fn,
114
+ dep.inputs.length,
115
+ dep.outputs.length
116
+ );
117
+ create_target_meta(dep.targets, dep.id, _target_map);
118
+ get_inputs_outputs(dep, inputs, outputs);
119
+ });
120
+
121
+ target_map.set(_target_map);
122
+
123
+ constructor_map = preload_all_components(components, root);
124
+
125
+ instance_map = components.reduce(
126
+ (acc, c) => {
127
+ acc[c.id] = c;
128
+ return acc;
129
+ },
130
+ {} as { [id: number]: ComponentMeta }
131
+ );
132
+
133
+ walk_layout(layout, root).then(() => {
134
+ layout_store.set(_rootNode);
135
+ });
136
+ }
137
+
138
+ /**
139
+ * Rerender the layout when the config has been modified to attach new components
140
+ */
141
+ function rerender_layout({
142
+ render_id,
143
+ components,
144
+ layout,
145
+ root,
146
+ dependencies
147
+ }: {
148
+ render_id: number;
149
+ components: ComponentMeta[];
150
+ layout: LayoutNode;
151
+ root: string;
152
+ dependencies: Dependency[];
153
+ }): void {
154
+ let _constructor_map = preload_all_components(components, root);
155
+ _constructor_map.forEach((v, k) => {
156
+ constructor_map.set(k, v);
157
+ });
158
+
159
+ _target_map = {};
160
+
161
+ dependencies.forEach((dep) => {
162
+ loading_status.register(dep.id, dep.inputs, dep.outputs);
163
+ dep.frontend_fn = process_frontend_fn(
164
+ dep.js,
165
+ !!dep.backend_fn,
166
+ dep.inputs.length,
167
+ dep.outputs.length
168
+ );
169
+ create_target_meta(dep.targets, dep.id, _target_map);
170
+ get_inputs_outputs(dep, inputs, outputs);
171
+ });
172
+
173
+ target_map.set(_target_map);
174
+
175
+ let current_element = instance_map[layout.id];
176
+ let all_current_children: ComponentMeta[] = [];
177
+ const add_to_current_children = (component: ComponentMeta): void => {
178
+ all_current_children.push(component);
179
+ if (component.children) {
180
+ component.children.forEach((child) => {
181
+ add_to_current_children(child);
182
+ });
183
+ }
184
+ };
185
+ add_to_current_children(current_element);
186
+ store_keyed_values(all_current_children);
187
+
188
+ Object.entries(instance_map).forEach(([id, component]) => {
189
+ let _id = Number(id);
190
+ if (component.rendered_in === render_id) {
191
+ delete instance_map[_id];
192
+ if (_component_map.has(_id)) {
193
+ _component_map.delete(_id);
194
+ }
195
+ }
196
+ });
197
+
198
+ components.forEach((c) => {
199
+ instance_map[c.id] = c;
200
+ _component_map.set(c.id, c);
201
+ });
202
+ if (current_element.parent) {
203
+ current_element.parent.children![
204
+ current_element.parent.children!.indexOf(current_element)
205
+ ] = instance_map[layout.id];
206
+ }
207
+
208
+ walk_layout(layout, root, current_element.parent).then(() => {
209
+ layout_store.set(_rootNode);
210
+ });
211
+ }
212
+
213
+ async function walk_layout(
214
+ node: LayoutNode,
215
+ root: string,
216
+ parent?: ComponentMeta
217
+ ): Promise<ComponentMeta> {
218
+ const instance = instance_map[node.id];
219
+
220
+ instance.component = (await constructor_map.get(
221
+ instance.component_class_id || instance.type
222
+ ))!?.default;
223
+ instance.parent = parent;
224
+
225
+ if (instance.type === "dataset") {
226
+ instance.props.component_map = get_component(
227
+ instance.type,
228
+ instance.component_class_id,
229
+ root,
230
+ _components,
231
+ instance.props.components
232
+ ).example_components;
233
+ }
234
+
235
+ if (_target_map[instance.id]) {
236
+ instance.props.attached_events = Object.keys(_target_map[instance.id]);
237
+ }
238
+
239
+ instance.props.interactive = determine_interactivity(
240
+ instance.id,
241
+ instance.props.interactive,
242
+ instance.props.value,
243
+ inputs,
244
+ outputs
245
+ );
246
+
247
+ instance.props.server = process_server_fn(
248
+ instance.id,
249
+ instance.props.server_fns,
250
+ app
251
+ );
252
+
253
+ if (
254
+ instance.key != null &&
255
+ keyed_component_values[instance.key] !== undefined
256
+ ) {
257
+ instance.props.value = keyed_component_values[instance.key];
258
+ }
259
+
260
+ _component_map.set(instance.id, instance);
261
+
262
+ if (node.children) {
263
+ instance.children = await Promise.all(
264
+ node.children.map((v) => walk_layout(v, root, instance))
265
+ );
266
+ }
267
+
268
+ return instance;
269
+ }
270
+
271
+ let update_scheduled = false;
272
+ let update_scheduled_store = writable(false);
273
+
274
+ function store_keyed_values(components: ComponentMeta[]): void {
275
+ components.forEach((c) => {
276
+ if (c.key != null) {
277
+ keyed_component_values[c.key] = c.props.value;
278
+ }
279
+ });
280
+ }
281
+
282
+ function flush(): void {
283
+ layout_store.update((layout) => {
284
+ for (let i = 0; i < pending_updates.length; i++) {
285
+ for (let j = 0; j < pending_updates[i].length; j++) {
286
+ const update = pending_updates[i][j];
287
+ if (!update) continue;
288
+ const instance = instance_map[update.id];
289
+ if (!instance) continue;
290
+ let new_value;
291
+ if (update.value instanceof Map) new_value = new Map(update.value);
292
+ else if (update.value instanceof Set)
293
+ new_value = new Set(update.value);
294
+ else if (Array.isArray(update.value)) new_value = [...update.value];
295
+ else if (update.value === null) new_value = null;
296
+ else if (typeof update.value === "object")
297
+ new_value = { ...update.value };
298
+ else new_value = update.value;
299
+ instance.props[update.prop] = new_value;
300
+ }
301
+ }
302
+ return layout;
303
+ });
304
+
305
+ pending_updates = [];
306
+ update_scheduled = false;
307
+ update_scheduled_store.set(false);
308
+ }
309
+
310
+ function update_value(updates: UpdateTransaction[] | undefined): void {
311
+ if (!updates) return;
312
+ pending_updates.push(updates);
313
+
314
+ if (!update_scheduled) {
315
+ update_scheduled = true;
316
+ update_scheduled_store.set(true);
317
+ requestAnimationFrame(flush);
318
+ }
319
+ }
320
+
321
+ function get_data(id: number): any | Promise<any> {
322
+ const comp = _component_map.get(id);
323
+ if (!comp) {
324
+ return null;
325
+ }
326
+ if (comp.instance.get_value) {
327
+ return comp.instance.get_value() as Promise<any>;
328
+ }
329
+ return comp.props.value;
330
+ }
331
+
332
+ return {
333
+ layout: layout_store,
334
+ targets: target_map,
335
+ update_value,
336
+ get_data,
337
+ loading_status,
338
+ scheduled_updates: update_scheduled_store,
339
+ create_layout: (...args) =>
340
+ requestAnimationFrame(() => create_layout(...args)),
341
+ rerender_layout
342
+ };
343
+ }
344
+
345
+ /** An async version of 'new Function' */
346
+ export const AsyncFunction: new (
347
+ ...args: string[]
348
+ ) => (...args: any[]) => Promise<any> = Object.getPrototypeOf(
349
+ async function () {}
350
+ ).constructor;
351
+
352
+ /**
353
+ * Takes a string of source code and returns a function that can be called with arguments
354
+ * @param source the source code
355
+ * @param backend_fn if there is also a backend function
356
+ * @param input_length the number of inputs
357
+ * @param output_length the number of outputs
358
+ * @returns The function, or null if the source code is invalid or missing
359
+ */
360
+ export function process_frontend_fn(
361
+ source: string | null | undefined | false,
362
+ backend_fn: boolean,
363
+ input_length: number,
364
+ output_length: number
365
+ ): ((...args: unknown[]) => Promise<unknown[]>) | null {
366
+ if (!source) return null;
367
+
368
+ const wrap = backend_fn ? input_length === 1 : output_length === 1;
369
+ try {
370
+ return new AsyncFunction(
371
+ "__fn_args",
372
+ ` let result = await (${source})(...__fn_args);
373
+ if (typeof result === "undefined") return [];
374
+ return (${wrap} && !Array.isArray(result)) ? [result] : result;`
375
+ );
376
+ } catch (e) {
377
+ console.error("Could not parse custom js method.");
378
+ console.error(e);
379
+ return null;
380
+ }
381
+ }
382
+
383
+ /**
384
+ * `Dependency.targets` is an array of `[id, trigger]` pairs with the ids as the `fn_id`.
385
+ * This function take a single list of `Dependency.targets` and add those to the target_map.
386
+ * @param targets the targets array
387
+ * @param fn_id the function index
388
+ * @param target_map the target map
389
+ * @returns the tagert map
390
+ */
391
+ export function create_target_meta(
392
+ targets: Dependency["targets"],
393
+ fn_id: number,
394
+ target_map: TargetMap
395
+ ): TargetMap {
396
+ targets.forEach(([id, trigger]) => {
397
+ if (!target_map[id]) {
398
+ target_map[id] = {};
399
+ }
400
+ if (
401
+ target_map[id]?.[trigger] &&
402
+ !target_map[id]?.[trigger].includes(fn_id)
403
+ ) {
404
+ target_map[id][trigger].push(fn_id);
405
+ } else {
406
+ target_map[id][trigger] = [fn_id];
407
+ }
408
+ });
409
+
410
+ return target_map;
411
+ }
412
+
413
+ /**
414
+ * Get all component ids that are an input or output of a dependency
415
+ * @param dep the dependency
416
+ * @param inputs the set of inputs
417
+ * @param outputs the set of outputs
418
+ * @returns a tuple of the inputs and outputs
419
+ */
420
+ export function get_inputs_outputs(
421
+ dep: Dependency,
422
+ inputs: Set<number>,
423
+ outputs: Set<number>
424
+ ): [Set<number>, Set<number>] {
425
+ dep.inputs.forEach((input) => inputs.add(input));
426
+ dep.outputs.forEach((output) => outputs.add(output));
427
+ return [inputs, outputs];
428
+ }
429
+
430
+ /**
431
+ * Check if a value is not a default value
432
+ * @param value the value to check
433
+ * @returns default value boolean
434
+ */
435
+ function has_no_default_value(value: any): boolean {
436
+ return (
437
+ (Array.isArray(value) && value.length === 0) ||
438
+ value === "" ||
439
+ value === 0 ||
440
+ !value
441
+ );
442
+ }
443
+
444
+ /**
445
+ * Determines if a component is interactive
446
+ * @param id component id
447
+ * @param interactive_prop value of the interactive prop
448
+ * @param value the main value of the component
449
+ * @param inputs set of ids that are inputs to a dependency
450
+ * @param outputs set of ids that are outputs to a dependency
451
+ * @returns if the component is interactive
452
+ */
453
+ export function determine_interactivity(
454
+ id: number,
455
+ interactive_prop: boolean | undefined,
456
+ value: any,
457
+ inputs: Set<number>,
458
+ outputs: Set<number>
459
+ ): boolean {
460
+ if (interactive_prop === false) {
461
+ return false;
462
+ } else if (interactive_prop === true) {
463
+ return true;
464
+ } else if (
465
+ inputs.has(id) ||
466
+ (!outputs.has(id) && has_no_default_value(value))
467
+ ) {
468
+ return true;
469
+ }
470
+
471
+ return false;
472
+ }
473
+
474
+ type ServerFunctions = Record<string, (...args: any[]) => Promise<any>>;
475
+
476
+ /**
477
+ * Process the server function names and return a dictionary of functions
478
+ * @param id the component id
479
+ * @param server_fns the server function names
480
+ * @param app the client instance
481
+ * @returns the actual server functions
482
+ */
483
+ export function process_server_fn(
484
+ id: number,
485
+ server_fns: string[] | undefined,
486
+ app: client_return
487
+ ): ServerFunctions {
488
+ if (!server_fns) {
489
+ return {};
490
+ }
491
+ return server_fns.reduce((acc, fn: string) => {
492
+ acc[fn] = async (...args: any[]) => {
493
+ if (args.length === 1) {
494
+ args = args[0];
495
+ }
496
+ const result = await app.component_server(id, fn, args);
497
+ return result;
498
+ };
499
+ return acc;
500
+ }, {} as ServerFunctions);
501
+ }
502
+
503
+ /**
504
+ * Get a component from the backend
505
+ * @param type the type of the component
506
+ * @param class_id the class id of the component
507
+ * @param root the root url of the app
508
+ * @param components the list of component metadata
509
+ * @param example_components the list of example components
510
+ * @returns the component and its name
511
+ */
512
+ export function get_component(
513
+ type: string,
514
+ class_id: string,
515
+ root: string,
516
+ components: ComponentMeta[],
517
+ example_components?: string[]
518
+ ): {
519
+ component: LoadingComponent;
520
+ name: ComponentMeta["type"];
521
+ example_components?: Map<ComponentMeta["type"], LoadingComponent>;
522
+ } {
523
+ let example_component_map: Map<ComponentMeta["type"], LoadingComponent> =
524
+ new Map();
525
+ if (type === "dataset" && example_components) {
526
+ (example_components as string[]).forEach((name: string) => {
527
+ if (example_component_map.has(name)) {
528
+ return;
529
+ }
530
+ let _c;
531
+
532
+ const matching_component = components.find((c) => c.type === name);
533
+ if (matching_component) {
534
+ _c = load_component({
535
+ api_url: root,
536
+ name,
537
+ id: matching_component.component_class_id,
538
+ variant: "example"
539
+ });
540
+ example_component_map.set(name, _c.component);
541
+ }
542
+ });
543
+ }
544
+
545
+ const _c = load_component({
546
+ api_url: root,
547
+ name: type,
548
+ id: class_id,
549
+ variant: "component"
550
+ });
551
+
552
+ return {
553
+ component: _c.component,
554
+ name: _c.name,
555
+ example_components:
556
+ example_component_map.size > 0 ? example_component_map : undefined
557
+ };
558
+ }
559
+
560
+ /**
561
+ * Preload all components
562
+ * @param components A list of component metadata
563
+ * @param root The root url of the app
564
+ * @returns A map of component ids to their constructors
565
+ */
566
+ export function preload_all_components(
567
+ components: ComponentMeta[],
568
+ root: string
569
+ ): Map<ComponentMeta["type"], LoadingComponent> {
570
+ let constructor_map: Map<ComponentMeta["type"], LoadingComponent> = new Map();
571
+
572
+ components.forEach((c) => {
573
+ const { component, example_components } = get_component(
574
+ c.type,
575
+ c.component_class_id,
576
+ root,
577
+ components
578
+ );
579
+
580
+ constructor_map.set(c.component_class_id || c.type, component);
581
+
582
+ if (example_components) {
583
+ for (const [name, example_component] of example_components) {
584
+ constructor_map.set(name, example_component);
585
+ }
586
+ }
587
+ });
588
+
589
+ return constructor_map;
590
+ }
@@ -0,0 +1,58 @@
1
+ // BCP47 locales are used to identify language variants + are composed of a ISO 639x language code and a region code
2
+ const BCP47_codes = [
3
+ "ar-SA",
4
+ "bn-BD",
5
+ "bn-IN",
6
+ "cs-CZ",
7
+ "da-DK",
8
+ "de-AT",
9
+ "de-CH",
10
+ "de-DE",
11
+ "el-GR",
12
+ "en-AU",
13
+ "en-CA",
14
+ "en-GB",
15
+ "en-IE",
16
+ "en-IN",
17
+ "en-NZ",
18
+ "en-US",
19
+ "en-ZA",
20
+ "es-AR",
21
+ "es-CL",
22
+ "es-CO",
23
+ "es-ES",
24
+ "es-MX",
25
+ "es-US",
26
+ "fi-FI",
27
+ "fr-BE",
28
+ "fr-CA",
29
+ "fr-CH",
30
+ "fr-FR",
31
+ "he-IL",
32
+ "hi-IN",
33
+ "hu-HU",
34
+ "id-ID",
35
+ "it-CH",
36
+ "it-IT",
37
+ "ja-JP",
38
+ "ko-KR",
39
+ "nl-BE",
40
+ "nl-NL",
41
+ "no-NO",
42
+ "pl-PL",
43
+ "pt-BR",
44
+ "pt-PT",
45
+ "ro-RO",
46
+ "ru-RU",
47
+ "sk-SK",
48
+ "sv-SE",
49
+ "ta-IN",
50
+ "ta-LK",
51
+ "th-TH",
52
+ "tr-TR",
53
+ "zh-CN",
54
+ "zh-HK",
55
+ "zh-TW"
56
+ ];
57
+
58
+ export default BCP47_codes;
@@ -0,0 +1,11 @@
1
+ # How to add support for more languages
2
+
3
+ We would love to support more languages for Gradio 🌎
4
+
5
+ To add your language, do the following steps:
6
+
7
+ 1. Create a new json file in this directory
8
+ 2. Name the file after the language code (Here's a list: http://4umi.com/web/html/languagecodes.php)
9
+ 3. Please provide clear and complete translations. Take a look at the [`en.json`](https://github.com/gradio-app/gradio/blob/master/js/core/public/lang/en.json) file for the corresponding English text.
10
+
11
+ That's it!
@@ -0,0 +1,16 @@
1
+ {
2
+ "common": {
3
+ "built_with_gradio": "تم الإنشاء بإستخدام Gradio",
4
+ "clear": "أمسح",
5
+ "or": "أو",
6
+ "submit": "أرسل"
7
+ },
8
+ "upload_text": {
9
+ "click_to_upload": "إضغط للتحميل",
10
+ "drop_audio": "أسقط الملف الصوتي هنا",
11
+ "drop_csv": "أسقط ملف البيانات هنا",
12
+ "drop_file": "أسقط الملف هنا",
13
+ "drop_image": "أسقط الصورة هنا",
14
+ "drop_video": "أسقط الفيديو هنا"
15
+ }
16
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "common": {
3
+ "built_with_gradio": "Construït amb gradio",
4
+ "clear": "Neteja",
5
+ "empty": "Buit",
6
+ "error": "Error",
7
+ "loading": "S'està carregant",
8
+ "or": "o",
9
+ "submit": "Envia"
10
+ },
11
+ "upload_text": {
12
+ "click_to_upload": "Feu clic per pujar",
13
+ "drop_audio": "Deixeu anar l'àudio aquí",
14
+ "drop_csv": "Deixeu anar el CSV aquí",
15
+ "drop_file": "Deixeu anar el fitxer aquí",
16
+ "drop_image": "Deixeu anar la imatge aquí",
17
+ "drop_video": "Deixeu anar el vídeo aquí"
18
+ }
19
+ }