@gradio/core 0.14.1 → 0.15.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/CHANGELOG.md +40 -0
- package/dist/src/gradio_helper.d.ts +14 -0
- package/dist/src/gradio_helper.js +42 -2
- package/dist/src/i18n.d.ts +1 -0
- package/dist/src/i18n.js +22 -3
- package/dist/src/lang/en.json +2 -1
- package/dist/src/lang/es.json +1 -0
- package/dist/src/lang/fr.json +3 -1
- package/dist/src/stories/I18nMultiLanguageTest.stories.d.ts +12 -0
- package/dist/src/stories/I18nMultiLanguageTest.stories.js +12 -0
- package/dist/src/stories/I18nMultiLanguageTestComponent.svelte +107 -0
- package/dist/src/stories/I18nMultiLanguageTestComponent.svelte.d.ts +16 -0
- package/dist/src/stories/I18nTestSetup.svelte +29 -0
- package/dist/src/stories/I18nTestSetup.svelte.d.ts +16 -0
- package/package.json +49 -48
- package/src/gradio_helper.ts +51 -3
- package/src/i18n.ts +34 -3
- package/src/lang/en.json +2 -1
- package/src/lang/es.json +1 -0
- package/src/lang/fr.json +3 -1
- package/src/stories/I18nMultiLanguageTest.stories.ts +17 -0
- package/src/stories/I18nMultiLanguageTestComponent.svelte +109 -0
- package/src/stories/I18nTestSetup.svelte +32 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @gradio/core
|
|
2
2
|
|
|
3
|
+
## 0.15.1
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- [#11088](https://github.com/gradio-app/gradio/pull/11088) [`a5105cc`](https://github.com/gradio-app/gradio/commit/a5105cccd6ca0682bd206608a080e24d69dad136) - fix: ensure all translation files work as expected. Thanks @Col0ring!
|
|
8
|
+
|
|
9
|
+
### Dependency updates
|
|
10
|
+
|
|
11
|
+
- @gradio/gallery@0.15.17
|
|
12
|
+
- @gradio/button@0.4.17
|
|
13
|
+
- @gradio/video@0.14.12
|
|
14
|
+
- @gradio/image@0.22.4
|
|
15
|
+
|
|
16
|
+
## 0.15.0
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
- [#11027](https://github.com/gradio-app/gradio/pull/11027) [`eff532b`](https://github.com/gradio-app/gradio/commit/eff532b913a3c8f06f10a4f9471d3177e3744053) - Add new `ImageSlider` component. Thanks @pngwn!
|
|
21
|
+
|
|
22
|
+
### Fixes
|
|
23
|
+
|
|
24
|
+
- [#11049](https://github.com/gradio-app/gradio/pull/11049) [`8d2aa3e`](https://github.com/gradio-app/gradio/commit/8d2aa3e99e165413bae1d8f5f3b4630e870308f5) - Ensure translations work as expected. Thanks @hannahblair!
|
|
25
|
+
|
|
26
|
+
### Dependency updates
|
|
27
|
+
|
|
28
|
+
- @gradio/code@0.14.2
|
|
29
|
+
- @gradio/paramviewer@0.7.8
|
|
30
|
+
- @gradio/statustracker@0.10.10
|
|
31
|
+
- @gradio/image@0.22.3
|
|
32
|
+
- @gradio/upload@0.16.3
|
|
33
|
+
- @gradio/button@0.4.16
|
|
34
|
+
- @gradio/video@0.14.11
|
|
35
|
+
- @gradio/atoms@0.16.0
|
|
36
|
+
- @gradio/column@0.2.0
|
|
37
|
+
- @gradio/gallery@0.15.16
|
|
38
|
+
- @gradio/plot@0.9.15
|
|
39
|
+
- @gradio/textbox@0.10.10
|
|
40
|
+
- @gradio/checkbox@0.4.20
|
|
41
|
+
- @gradio/file@0.12.16
|
|
42
|
+
|
|
3
43
|
## 0.14.1
|
|
4
44
|
|
|
5
45
|
### Fixes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { Gradio } from "@gradio/utils";
|
|
2
|
+
export type I18nFormatter = typeof formatter;
|
|
3
|
+
/**
|
|
4
|
+
* i18n formatter with fallback to svelte-i18n's format function.
|
|
5
|
+
*
|
|
6
|
+
* @param value - The string to translate or format
|
|
7
|
+
* @returns The translated string
|
|
8
|
+
*
|
|
9
|
+
* This formatter attempts translation in the following order:
|
|
10
|
+
* 1. Direct translation of the input string
|
|
11
|
+
* 2. Checks if input matches any common key names
|
|
12
|
+
* 3. Falls back to svelte-i18n's format function
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatter(value: string | null | undefined): string;
|
|
@@ -1,4 +1,44 @@
|
|
|
1
|
-
import { format } from "svelte-i18n";
|
|
1
|
+
import { format, _ } from "svelte-i18n";
|
|
2
2
|
import { get } from "svelte/store";
|
|
3
|
+
import { all_common_keys } from "./i18n";
|
|
3
4
|
export { Gradio } from "@gradio/utils";
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* i18n formatter with fallback to svelte-i18n's format function.
|
|
7
|
+
*
|
|
8
|
+
* @param value - The string to translate or format
|
|
9
|
+
* @returns The translated string
|
|
10
|
+
*
|
|
11
|
+
* This formatter attempts translation in the following order:
|
|
12
|
+
* 1. Direct translation of the input string
|
|
13
|
+
* 2. Checks if input matches any common key names
|
|
14
|
+
* 3. Falls back to svelte-i18n's format function
|
|
15
|
+
*/
|
|
16
|
+
export function formatter(value) {
|
|
17
|
+
if (value == null) {
|
|
18
|
+
return "";
|
|
19
|
+
}
|
|
20
|
+
const string_value = String(value);
|
|
21
|
+
const translate = get(_);
|
|
22
|
+
const initial_formatter = get(format);
|
|
23
|
+
let direct_translation = translate(string_value);
|
|
24
|
+
if (direct_translation !== string_value) {
|
|
25
|
+
return direct_translation;
|
|
26
|
+
}
|
|
27
|
+
const lower_value = string_value.toLowerCase();
|
|
28
|
+
for (const common_key of all_common_keys) {
|
|
29
|
+
const key_name = common_key.substring(common_key.indexOf(".") + 1);
|
|
30
|
+
if (lower_value === key_name) {
|
|
31
|
+
const translation = translate(common_key);
|
|
32
|
+
if (translation !== common_key) {
|
|
33
|
+
return translation;
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// fall back to the svelte-i18n formatter to maintain compatibility
|
|
39
|
+
const formatted = initial_formatter(string_value);
|
|
40
|
+
if (formatted !== string_value) {
|
|
41
|
+
return formatted;
|
|
42
|
+
}
|
|
43
|
+
return string_value;
|
|
44
|
+
}
|
package/dist/src/i18n.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ type LangsRecord = Record<string, {
|
|
|
3
3
|
}>;
|
|
4
4
|
export declare function process_langs(): LangsRecord;
|
|
5
5
|
export declare const language_choices: [string, string][];
|
|
6
|
+
export declare let all_common_keys: Set<string>;
|
|
6
7
|
export declare function setupi18n(): Promise<void>;
|
|
7
8
|
export declare function changeLocale(new_locale: string): void;
|
|
8
9
|
export {};
|
package/dist/src/i18n.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addMessages, init, getLocaleFromNavigator, locale } from "svelte-i18n";
|
|
1
|
+
import { addMessages, init, getLocaleFromNavigator, locale, _ } from "svelte-i18n";
|
|
2
2
|
const langs = import.meta.glob("./lang/*.json", {
|
|
3
3
|
eager: true
|
|
4
4
|
});
|
|
@@ -13,6 +13,7 @@ export function process_langs() {
|
|
|
13
13
|
const processed_langs = process_langs();
|
|
14
14
|
const available_locales = Object.keys(processed_langs);
|
|
15
15
|
export const language_choices = Object.entries(processed_langs).map(([code, data]) => [data._name || code, code]);
|
|
16
|
+
export let all_common_keys = new Set();
|
|
16
17
|
for (const lang in processed_langs) {
|
|
17
18
|
addMessages(lang, processed_langs[lang]);
|
|
18
19
|
}
|
|
@@ -22,13 +23,31 @@ export async function setupi18n() {
|
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
25
|
const browser_locale = getLocaleFromNavigator();
|
|
25
|
-
|
|
26
|
+
let initial_locale = browser_locale && available_locales.includes(browser_locale)
|
|
26
27
|
? browser_locale
|
|
27
|
-
:
|
|
28
|
+
: null;
|
|
29
|
+
if (!initial_locale) {
|
|
30
|
+
const normalized_locale = browser_locale?.split("-")[0];
|
|
31
|
+
initial_locale =
|
|
32
|
+
normalized_locale && available_locales.includes(normalized_locale)
|
|
33
|
+
? normalized_locale
|
|
34
|
+
: "en";
|
|
35
|
+
}
|
|
28
36
|
await init({
|
|
29
37
|
fallbackLocale: "en",
|
|
30
38
|
initialLocale: initial_locale
|
|
31
39
|
});
|
|
40
|
+
for (const lang_code in processed_langs) {
|
|
41
|
+
if (processed_langs[lang_code] &&
|
|
42
|
+
typeof processed_langs[lang_code] === "object" &&
|
|
43
|
+
processed_langs[lang_code].common &&
|
|
44
|
+
typeof processed_langs[lang_code].common === "object") {
|
|
45
|
+
const common_ns = processed_langs[lang_code].common;
|
|
46
|
+
for (const key in common_ns) {
|
|
47
|
+
all_common_keys.add(`common.${key}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
32
51
|
i18n_initialized = true;
|
|
33
52
|
}
|
|
34
53
|
export function changeLocale(new_locale) {
|
package/dist/src/lang/en.json
CHANGED
|
@@ -68,7 +68,8 @@
|
|
|
68
68
|
"no_devices": "No devices found",
|
|
69
69
|
"language": "Language",
|
|
70
70
|
"display_theme": "Display Theme",
|
|
71
|
-
"pwa": "Progressive Web App"
|
|
71
|
+
"pwa": "Progressive Web App",
|
|
72
|
+
"run": "Run"
|
|
72
73
|
},
|
|
73
74
|
"dataframe": {
|
|
74
75
|
"incorrect_format": "Incorrect format, only CSV and TSV files are supported",
|
package/dist/src/lang/es.json
CHANGED
package/dist/src/lang/fr.json
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"download": "Télécharger",
|
|
46
46
|
"edit": "Modifier",
|
|
47
47
|
"empty": "Vide",
|
|
48
|
+
"flag": "Marquer",
|
|
48
49
|
"error": "Erreur",
|
|
49
50
|
"hosted_on": "Hébergé sur",
|
|
50
51
|
"loading": "Chargement",
|
|
@@ -58,7 +59,8 @@
|
|
|
58
59
|
"no_devices": "Aucun périphérique trouvé",
|
|
59
60
|
"language": "Langue",
|
|
60
61
|
"display_theme": "Thème d'affichage",
|
|
61
|
-
"pwa": "Application web progressive"
|
|
62
|
+
"pwa": "Application web progressive",
|
|
63
|
+
"run": "Exécuter"
|
|
62
64
|
},
|
|
63
65
|
"dataframe": {
|
|
64
66
|
"incorrect_format": "Format incorrect, seuls les fichiers CSV et TSV sont pris en charge",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StoryObj } from "@storybook/svelte";
|
|
2
|
+
import I18nMultiLanguageTestComponent from "./I18nMultiLanguageTestComponent.svelte";
|
|
3
|
+
declare const meta: {
|
|
4
|
+
title: string;
|
|
5
|
+
component: typeof I18nMultiLanguageTestComponent;
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
export declare const Default: Story;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import I18nMultiLanguageTestComponent from "./I18nMultiLanguageTestComponent.svelte";
|
|
2
|
+
const meta = {
|
|
3
|
+
title: "Core/I18n Multi-Language Test",
|
|
4
|
+
component: I18nMultiLanguageTestComponent,
|
|
5
|
+
parameters: {
|
|
6
|
+
layout: "centered"
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
export default meta;
|
|
10
|
+
export const Default = {
|
|
11
|
+
args: {}
|
|
12
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script>import { formatter } from "../gradio_helper";
|
|
2
|
+
import I18nTestSetup from "./I18nTestSetup.svelte";
|
|
3
|
+
const testStrings = ["share", "submit", "clear", "flag", "error"];
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<I18nTestSetup />
|
|
7
|
+
|
|
8
|
+
<div class="i18n-multi-language-container">
|
|
9
|
+
<h2>I18n Formatter Test</h2>
|
|
10
|
+
|
|
11
|
+
<div class="translation-table">
|
|
12
|
+
<div class="table-header">
|
|
13
|
+
<div class="col">String Key</div>
|
|
14
|
+
<div class="col">Common Key</div>
|
|
15
|
+
<div class="col">Formatted Output</div>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
{#each testStrings as str}
|
|
19
|
+
<div class="table-row">
|
|
20
|
+
<div class="col key">{str}</div>
|
|
21
|
+
<div class="col key">common.{str}</div>
|
|
22
|
+
<div class="col result">{formatter(str)}</div>
|
|
23
|
+
</div>
|
|
24
|
+
{/each}
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="instructions">
|
|
28
|
+
<h3>Testing</h3>
|
|
29
|
+
Use the <strong>Locale</strong> selector in the toolbar to change languages
|
|
30
|
+
and refresh
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
.i18n-multi-language-container {
|
|
36
|
+
padding: 2rem;
|
|
37
|
+
border-radius: 0.5rem;
|
|
38
|
+
border: 1px solid #e2e8f0;
|
|
39
|
+
margin: 1rem;
|
|
40
|
+
max-width: 700px;
|
|
41
|
+
font-family:
|
|
42
|
+
system-ui,
|
|
43
|
+
-apple-system,
|
|
44
|
+
sans-serif;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
h2 {
|
|
48
|
+
margin-top: 0;
|
|
49
|
+
margin-bottom: 1rem;
|
|
50
|
+
font-size: 1.5rem;
|
|
51
|
+
font-weight: 600;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
h3 {
|
|
55
|
+
font-size: 1.1rem;
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
margin-bottom: 0.75rem;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.translation-table {
|
|
61
|
+
border: 1px solid #e2e8f0;
|
|
62
|
+
border-radius: 0.5rem;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
margin-bottom: 1.5rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.table-header {
|
|
68
|
+
display: flex;
|
|
69
|
+
background-color: #f8fafc;
|
|
70
|
+
font-weight: 600;
|
|
71
|
+
border-bottom: 1px solid #e2e8f0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.table-row {
|
|
75
|
+
display: flex;
|
|
76
|
+
border-bottom: 1px solid #e2e8f0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.table-row:last-child {
|
|
80
|
+
border-bottom: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.col {
|
|
84
|
+
padding: 0.75rem 1rem;
|
|
85
|
+
flex: 1;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.col:not(:last-child) {
|
|
89
|
+
border-right: 1px solid #e2e8f0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.key {
|
|
93
|
+
font-family: monospace;
|
|
94
|
+
background-color: #f8fafc;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.result {
|
|
98
|
+
font-weight: 500;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.instructions {
|
|
102
|
+
padding: 1rem;
|
|
103
|
+
background-color: #f0f9ff;
|
|
104
|
+
border-radius: 0.5rem;
|
|
105
|
+
font-size: 0.9rem;
|
|
106
|
+
}
|
|
107
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
[x: string]: never;
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {};
|
|
10
|
+
};
|
|
11
|
+
export type I18nMultiLanguageTestComponentProps = typeof __propDef.props;
|
|
12
|
+
export type I18nMultiLanguageTestComponentEvents = typeof __propDef.events;
|
|
13
|
+
export type I18nMultiLanguageTestComponentSlots = typeof __propDef.slots;
|
|
14
|
+
export default class I18nMultiLanguageTestComponent extends SvelteComponent<I18nMultiLanguageTestComponentProps, I18nMultiLanguageTestComponentEvents, I18nMultiLanguageTestComponentSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script>import { onMount } from "svelte";
|
|
2
|
+
import { init, _ } from "svelte-i18n";
|
|
3
|
+
export let active = true;
|
|
4
|
+
onMount(async () => {
|
|
5
|
+
if (!active)
|
|
6
|
+
return;
|
|
7
|
+
await init({
|
|
8
|
+
fallbackLocale: "en",
|
|
9
|
+
initialLocale: "en"
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#if active}
|
|
15
|
+
<div class="i18n-test-setup">
|
|
16
|
+
<p>i18n test setup active - translations loaded for: en, fr, de, es, ar</p>
|
|
17
|
+
</div>
|
|
18
|
+
{/if}
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.i18n-test-setup {
|
|
22
|
+
font-size: 0.75rem;
|
|
23
|
+
color: #94a3b8;
|
|
24
|
+
margin-bottom: 0.5rem;
|
|
25
|
+
padding: 0.5rem;
|
|
26
|
+
background-color: #f1f5f9;
|
|
27
|
+
border-radius: 0.25rem;
|
|
28
|
+
}
|
|
29
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
active?: boolean | undefined;
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {};
|
|
10
|
+
};
|
|
11
|
+
export type I18nTestSetupProps = typeof __propDef.props;
|
|
12
|
+
export type I18nTestSetupEvents = typeof __propDef.events;
|
|
13
|
+
export type I18nTestSetupSlots = typeof __propDef.slots;
|
|
14
|
+
export default class I18nTestSetup extends SvelteComponent<I18nTestSetupProps, I18nTestSetupEvents, I18nTestSetupSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,67 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"devDependencies": {
|
|
6
|
-
"@gradio/accordion": "^0.5.
|
|
7
|
-
"@gradio/
|
|
8
|
-
"@gradio/audio": "^0.17.
|
|
9
|
-
"@gradio/button": "^0.4.
|
|
10
|
-
"@gradio/chatbot": "^0.26.
|
|
11
|
-
"@gradio/
|
|
12
|
-
"@gradio/
|
|
13
|
-
"@gradio/
|
|
14
|
-
"@gradio/checkboxgroup": "^0.6.19",
|
|
6
|
+
"@gradio/accordion": "^0.5.14",
|
|
7
|
+
"@gradio/atoms": "^0.16.0",
|
|
8
|
+
"@gradio/audio": "^0.17.12",
|
|
9
|
+
"@gradio/button": "^0.4.17",
|
|
10
|
+
"@gradio/chatbot": "^0.26.3",
|
|
11
|
+
"@gradio/checkbox": "^0.4.20",
|
|
12
|
+
"@gradio/checkboxgroup": "^0.6.20",
|
|
13
|
+
"@gradio/box": "^0.2.18",
|
|
15
14
|
"@gradio/client": "^1.14.2",
|
|
16
|
-
"@gradio/
|
|
17
|
-
"@gradio/
|
|
15
|
+
"@gradio/code": "^0.14.2",
|
|
16
|
+
"@gradio/colorpicker": "^0.4.20",
|
|
18
17
|
"@gradio/column": "^0.2.0",
|
|
19
|
-
"@gradio/
|
|
20
|
-
"@gradio/
|
|
21
|
-
"@gradio/downloadbutton": "^0.3.
|
|
22
|
-
"@gradio/
|
|
23
|
-
"@gradio/dropdown": "^0.9.
|
|
24
|
-
"@gradio/
|
|
25
|
-
"@gradio/
|
|
26
|
-
"@gradio/fileexplorer": "^0.5.
|
|
27
|
-
"@gradio/form": "^0.2.
|
|
28
|
-
"@gradio/
|
|
18
|
+
"@gradio/datetime": "^0.3.12",
|
|
19
|
+
"@gradio/dataframe": "^0.17.10",
|
|
20
|
+
"@gradio/downloadbutton": "^0.3.17",
|
|
21
|
+
"@gradio/dataset": "^0.4.16",
|
|
22
|
+
"@gradio/dropdown": "^0.9.20",
|
|
23
|
+
"@gradio/fallback": "^0.4.20",
|
|
24
|
+
"@gradio/file": "^0.12.16",
|
|
25
|
+
"@gradio/fileexplorer": "^0.5.27",
|
|
26
|
+
"@gradio/form": "^0.2.18",
|
|
27
|
+
"@gradio/annotatedimage": "^0.9.17",
|
|
28
|
+
"@gradio/gallery": "^0.15.17",
|
|
29
29
|
"@gradio/group": "^0.2.0",
|
|
30
|
-
"@gradio/highlightedtext": "^0.9.
|
|
31
|
-
"@gradio/html": "^0.6.
|
|
30
|
+
"@gradio/highlightedtext": "^0.9.3",
|
|
31
|
+
"@gradio/html": "^0.6.11",
|
|
32
32
|
"@gradio/icons": "^0.12.0",
|
|
33
|
-
"@gradio/image": "^0.22.
|
|
34
|
-
"@gradio/
|
|
35
|
-
"@gradio/
|
|
36
|
-
"@gradio/
|
|
37
|
-
"@gradio/markdown": "^0.13.9",
|
|
33
|
+
"@gradio/image": "^0.22.4",
|
|
34
|
+
"@gradio/imageslider": "^0.2.0",
|
|
35
|
+
"@gradio/imageeditor": "^0.14.4",
|
|
36
|
+
"@gradio/json": "^0.5.20",
|
|
38
37
|
"@gradio/browserstate": "^0.3.2",
|
|
39
|
-
"@gradio/
|
|
40
|
-
"@gradio/
|
|
41
|
-
"@gradio/
|
|
42
|
-
"@gradio/
|
|
43
|
-
"@gradio/
|
|
44
|
-
"@gradio/
|
|
45
|
-
"@gradio/
|
|
46
|
-
"@gradio/
|
|
38
|
+
"@gradio/markdown": "^0.13.10",
|
|
39
|
+
"@gradio/label": "^0.5.12",
|
|
40
|
+
"@gradio/multimodaltextbox": "^0.10.4",
|
|
41
|
+
"@gradio/model3d": "^0.14.11",
|
|
42
|
+
"@gradio/nativeplot": "^0.5.14",
|
|
43
|
+
"@gradio/number": "^0.5.20",
|
|
44
|
+
"@gradio/plot": "^0.9.15",
|
|
45
|
+
"@gradio/paramviewer": "^0.7.8",
|
|
46
|
+
"@gradio/radio": "^0.7.3",
|
|
47
47
|
"@gradio/row": "^0.2.1",
|
|
48
|
-
"@gradio/
|
|
49
|
-
"@gradio/
|
|
50
|
-
"@gradio/
|
|
51
|
-
"@gradio/
|
|
48
|
+
"@gradio/sidebar": "^0.1.12",
|
|
49
|
+
"@gradio/simpledropdown": "^0.3.20",
|
|
50
|
+
"@gradio/simpleimage": "^0.8.27",
|
|
51
|
+
"@gradio/sketchbox": "^0.6.7",
|
|
52
|
+
"@gradio/simpletextbox": "^0.3.20",
|
|
53
|
+
"@gradio/slider": "^0.6.8",
|
|
52
54
|
"@gradio/state": "^0.1.2",
|
|
53
|
-
"@gradio/statustracker": "^0.10.
|
|
55
|
+
"@gradio/statustracker": "^0.10.10",
|
|
54
56
|
"@gradio/tabitem": "^0.4.3",
|
|
55
|
-
"@gradio/slider": "^0.6.7",
|
|
56
57
|
"@gradio/tabs": "^0.4.3",
|
|
58
|
+
"@gradio/textbox": "^0.10.10",
|
|
57
59
|
"@gradio/theme": "^0.4.0",
|
|
58
|
-
"@gradio/textbox": "^0.10.9",
|
|
59
60
|
"@gradio/timer": "^0.4.5",
|
|
60
|
-
"@gradio/upload": "^0.16.
|
|
61
|
-
"@gradio/uploadbutton": "^0.8.
|
|
62
|
-
"@gradio/
|
|
61
|
+
"@gradio/upload": "^0.16.3",
|
|
62
|
+
"@gradio/uploadbutton": "^0.8.17",
|
|
63
|
+
"@gradio/video": "^0.14.12",
|
|
63
64
|
"@gradio/wasm": "^0.18.1",
|
|
64
|
-
"@gradio/
|
|
65
|
+
"@gradio/utils": "^0.10.2"
|
|
65
66
|
},
|
|
66
67
|
"msw": {
|
|
67
68
|
"workerDirectory": "public"
|
package/src/gradio_helper.ts
CHANGED
|
@@ -1,7 +1,55 @@
|
|
|
1
|
-
import { format } from "svelte-i18n";
|
|
1
|
+
import { format, _ } from "svelte-i18n";
|
|
2
2
|
import { get } from "svelte/store";
|
|
3
|
+
import { all_common_keys } from "./i18n";
|
|
4
|
+
|
|
3
5
|
export { Gradio } from "@gradio/utils";
|
|
6
|
+
export type I18nFormatter = typeof formatter;
|
|
4
7
|
|
|
5
|
-
|
|
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
|
+
export function formatter(value: string | null | undefined): string {
|
|
20
|
+
if (value == null) {
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
const string_value = String(value);
|
|
24
|
+
const translate = get(_);
|
|
25
|
+
const initial_formatter = get(format);
|
|
6
26
|
|
|
7
|
-
|
|
27
|
+
let direct_translation = translate(string_value);
|
|
28
|
+
|
|
29
|
+
if (direct_translation !== string_value) {
|
|
30
|
+
return direct_translation;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const lower_value = string_value.toLowerCase();
|
|
34
|
+
|
|
35
|
+
for (const common_key of all_common_keys) {
|
|
36
|
+
const key_name = common_key.substring(common_key.indexOf(".") + 1);
|
|
37
|
+
|
|
38
|
+
if (lower_value === key_name) {
|
|
39
|
+
const translation = translate(common_key);
|
|
40
|
+
|
|
41
|
+
if (translation !== common_key) {
|
|
42
|
+
return translation;
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
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
|
+
return string_value;
|
|
55
|
+
}
|
package/src/i18n.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
addMessages,
|
|
3
|
+
init,
|
|
4
|
+
getLocaleFromNavigator,
|
|
5
|
+
locale,
|
|
6
|
+
_
|
|
7
|
+
} from "svelte-i18n";
|
|
2
8
|
|
|
3
9
|
const langs = import.meta.glob("./lang/*.json", {
|
|
4
10
|
eager: true
|
|
@@ -29,6 +35,8 @@ export const language_choices: [string, string][] = Object.entries(
|
|
|
29
35
|
processed_langs
|
|
30
36
|
).map(([code, data]) => [data._name || code, code]);
|
|
31
37
|
|
|
38
|
+
export let all_common_keys: Set<string> = new Set();
|
|
39
|
+
|
|
32
40
|
for (const lang in processed_langs) {
|
|
33
41
|
addMessages(lang, processed_langs[lang]);
|
|
34
42
|
}
|
|
@@ -41,16 +49,39 @@ export async function setupi18n(): Promise<void> {
|
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
const browser_locale = getLocaleFromNavigator();
|
|
44
|
-
|
|
52
|
+
|
|
53
|
+
let initial_locale =
|
|
45
54
|
browser_locale && available_locales.includes(browser_locale)
|
|
46
55
|
? browser_locale
|
|
47
|
-
:
|
|
56
|
+
: null;
|
|
57
|
+
|
|
58
|
+
if (!initial_locale) {
|
|
59
|
+
const normalized_locale = browser_locale?.split("-")[0];
|
|
60
|
+
initial_locale =
|
|
61
|
+
normalized_locale && available_locales.includes(normalized_locale)
|
|
62
|
+
? normalized_locale
|
|
63
|
+
: "en";
|
|
64
|
+
}
|
|
48
65
|
|
|
49
66
|
await init({
|
|
50
67
|
fallbackLocale: "en",
|
|
51
68
|
initialLocale: initial_locale
|
|
52
69
|
});
|
|
53
70
|
|
|
71
|
+
for (const lang_code in processed_langs) {
|
|
72
|
+
if (
|
|
73
|
+
processed_langs[lang_code] &&
|
|
74
|
+
typeof processed_langs[lang_code] === "object" &&
|
|
75
|
+
processed_langs[lang_code].common &&
|
|
76
|
+
typeof processed_langs[lang_code].common === "object"
|
|
77
|
+
) {
|
|
78
|
+
const common_ns = processed_langs[lang_code].common;
|
|
79
|
+
for (const key in common_ns) {
|
|
80
|
+
all_common_keys.add(`common.${key}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
54
85
|
i18n_initialized = true;
|
|
55
86
|
}
|
|
56
87
|
|
package/src/lang/en.json
CHANGED
|
@@ -68,7 +68,8 @@
|
|
|
68
68
|
"no_devices": "No devices found",
|
|
69
69
|
"language": "Language",
|
|
70
70
|
"display_theme": "Display Theme",
|
|
71
|
-
"pwa": "Progressive Web App"
|
|
71
|
+
"pwa": "Progressive Web App",
|
|
72
|
+
"run": "Run"
|
|
72
73
|
},
|
|
73
74
|
"dataframe": {
|
|
74
75
|
"incorrect_format": "Incorrect format, only CSV and TSV files are supported",
|
package/src/lang/es.json
CHANGED
package/src/lang/fr.json
CHANGED
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"download": "Télécharger",
|
|
46
46
|
"edit": "Modifier",
|
|
47
47
|
"empty": "Vide",
|
|
48
|
+
"flag": "Marquer",
|
|
48
49
|
"error": "Erreur",
|
|
49
50
|
"hosted_on": "Hébergé sur",
|
|
50
51
|
"loading": "Chargement",
|
|
@@ -58,7 +59,8 @@
|
|
|
58
59
|
"no_devices": "Aucun périphérique trouvé",
|
|
59
60
|
"language": "Langue",
|
|
60
61
|
"display_theme": "Thème d'affichage",
|
|
61
|
-
"pwa": "Application web progressive"
|
|
62
|
+
"pwa": "Application web progressive",
|
|
63
|
+
"run": "Exécuter"
|
|
62
64
|
},
|
|
63
65
|
"dataframe": {
|
|
64
66
|
"incorrect_format": "Format incorrect, seuls les fichiers CSV et TSV sont pris en charge",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/svelte";
|
|
2
|
+
import I18nMultiLanguageTestComponent from "./I18nMultiLanguageTestComponent.svelte";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: "Core/I18n Multi-Language Test",
|
|
6
|
+
component: I18nMultiLanguageTestComponent,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: "centered"
|
|
9
|
+
}
|
|
10
|
+
} satisfies Meta<I18nMultiLanguageTestComponent>;
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
args: {}
|
|
17
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { formatter } from "../gradio_helper";
|
|
3
|
+
import I18nTestSetup from "./I18nTestSetup.svelte";
|
|
4
|
+
|
|
5
|
+
const testStrings = ["share", "submit", "clear", "flag", "error"];
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<I18nTestSetup />
|
|
9
|
+
|
|
10
|
+
<div class="i18n-multi-language-container">
|
|
11
|
+
<h2>I18n Formatter Test</h2>
|
|
12
|
+
|
|
13
|
+
<div class="translation-table">
|
|
14
|
+
<div class="table-header">
|
|
15
|
+
<div class="col">String Key</div>
|
|
16
|
+
<div class="col">Common Key</div>
|
|
17
|
+
<div class="col">Formatted Output</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
{#each testStrings as str}
|
|
21
|
+
<div class="table-row">
|
|
22
|
+
<div class="col key">{str}</div>
|
|
23
|
+
<div class="col key">common.{str}</div>
|
|
24
|
+
<div class="col result">{formatter(str)}</div>
|
|
25
|
+
</div>
|
|
26
|
+
{/each}
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="instructions">
|
|
30
|
+
<h3>Testing</h3>
|
|
31
|
+
Use the <strong>Locale</strong> selector in the toolbar to change languages
|
|
32
|
+
and refresh
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<style>
|
|
37
|
+
.i18n-multi-language-container {
|
|
38
|
+
padding: 2rem;
|
|
39
|
+
border-radius: 0.5rem;
|
|
40
|
+
border: 1px solid #e2e8f0;
|
|
41
|
+
margin: 1rem;
|
|
42
|
+
max-width: 700px;
|
|
43
|
+
font-family:
|
|
44
|
+
system-ui,
|
|
45
|
+
-apple-system,
|
|
46
|
+
sans-serif;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
h2 {
|
|
50
|
+
margin-top: 0;
|
|
51
|
+
margin-bottom: 1rem;
|
|
52
|
+
font-size: 1.5rem;
|
|
53
|
+
font-weight: 600;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
h3 {
|
|
57
|
+
font-size: 1.1rem;
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
margin-bottom: 0.75rem;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.translation-table {
|
|
63
|
+
border: 1px solid #e2e8f0;
|
|
64
|
+
border-radius: 0.5rem;
|
|
65
|
+
overflow: hidden;
|
|
66
|
+
margin-bottom: 1.5rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.table-header {
|
|
70
|
+
display: flex;
|
|
71
|
+
background-color: #f8fafc;
|
|
72
|
+
font-weight: 600;
|
|
73
|
+
border-bottom: 1px solid #e2e8f0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.table-row {
|
|
77
|
+
display: flex;
|
|
78
|
+
border-bottom: 1px solid #e2e8f0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.table-row:last-child {
|
|
82
|
+
border-bottom: none;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.col {
|
|
86
|
+
padding: 0.75rem 1rem;
|
|
87
|
+
flex: 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.col:not(:last-child) {
|
|
91
|
+
border-right: 1px solid #e2e8f0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.key {
|
|
95
|
+
font-family: monospace;
|
|
96
|
+
background-color: #f8fafc;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.result {
|
|
100
|
+
font-weight: 500;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.instructions {
|
|
104
|
+
padding: 1rem;
|
|
105
|
+
background-color: #f0f9ff;
|
|
106
|
+
border-radius: 0.5rem;
|
|
107
|
+
font-size: 0.9rem;
|
|
108
|
+
}
|
|
109
|
+
</style>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
import { init, _ } from "svelte-i18n";
|
|
4
|
+
|
|
5
|
+
export let active = true;
|
|
6
|
+
|
|
7
|
+
onMount(async () => {
|
|
8
|
+
if (!active) return;
|
|
9
|
+
|
|
10
|
+
await init({
|
|
11
|
+
fallbackLocale: "en",
|
|
12
|
+
initialLocale: "en"
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#if active}
|
|
18
|
+
<div class="i18n-test-setup">
|
|
19
|
+
<p>i18n test setup active - translations loaded for: en, fr, de, es, ar</p>
|
|
20
|
+
</div>
|
|
21
|
+
{/if}
|
|
22
|
+
|
|
23
|
+
<style>
|
|
24
|
+
.i18n-test-setup {
|
|
25
|
+
font-size: 0.75rem;
|
|
26
|
+
color: #94a3b8;
|
|
27
|
+
margin-bottom: 0.5rem;
|
|
28
|
+
padding: 0.5rem;
|
|
29
|
+
background-color: #f1f5f9;
|
|
30
|
+
border-radius: 0.25rem;
|
|
31
|
+
}
|
|
32
|
+
</style>
|