Repository: gradio-app/gradio
File: js/utils/src/utils.svelte.ts (TypeScript)

Code before:
	set_data(data: Partial<U & SharedProps>): void {
		for (const key in data) {
			if (this.shared_props.includes(key as keyof SharedProps)) {
				const _key = key as keyof SharedProps;
				// @ts-ignore i'm not doing pointless typescript gymanstics

				this.shared[_key] = data[_key];

				continue;

				// @ts-ignore same here
			} else {
				// @ts-ignore same here
				this.props[key] = data[key];
			}
		}
	}
}

// function _load_component(
// 	this: Gradio,
// 	name: string,
// 	variant: "component" | "example" | "base" = "component"
// ): ReturnType<component_loader> {
// 	return this._load_component!({
// 		name,
// 		api_url: this.shared.client.config?.root!,
// 		variant
// 	});
// }

export const css_units = (dimension_value: string | number): string => {
	return typeof dimension_value === "number"
		? dimension_value + "px"
		: dimension_value;
};

export function should_show_scroll_fade(
	container: HTMLElement | null
): boolean {
	if (!container) return false;
	const has_overflow = container.scrollHeight > container.clientHeight;
	const at_bottom =
		container.scrollTop >= container.scrollHeight - container.clientHeight - 1;
	return has_overflow && !at_bottom;
}

type MappedProps<T> = { [K in keyof T]: T[K] };
type MappedProp<T, K extends keyof T> = { [P in K]: T[P] };


Review comment (suggestion):
I was worried that doing this would mean that i18n with `@gr.render` would not work. However, I was able to test that it works correctly here:

```python
import gradio as gr

# create an i18n instance with translations for different languages
i18n = gr.I18n(
    en={"greeting": "Hello, welcome to my app!", "name_label": "Your Name", "submit_button": "Greet", "john_doe": "John English", "result_label": "Result"},
    es={"greeting": "¡Hola, bienvenido a mi aplicación!", "name_label": "Tu Nombre", "submit_button": "Saludar", "john_doe": "John Spanish", "result_label": "Resultado"},
    fr={"greeting": "Bonjour, bienvenue dans mon application!", "name_label": "Votre Nom", "submit_button": "Saluer", "john_doe": "John French", "result_label": "Résultat"},
    de={"greeting": "Hallo, willkommen in meiner App!", "name_label": "Dein Name", "submit_button": "Grüßen", "john_doe": "John German", "result_label": "Ergebnis"},
)

def add_hello_world(name):
    return "hello " + name

with gr.Blocks() as demo:

    button = gr.Button("Start Demo")
    @gr.render(triggers=[button.click])
    def _():
        gr.Markdown(value=i18n("greeting"))

        with gr.Row():
            # use i18n() for any string that should be translated
            name_input = gr.Textbox(label=i18n("name_label"), value=i18n("john_doe"), interactive=True)

        with gr.Row():
            output_text = gr.Textbox(label=i18n("result_label"))

        with gr.Row():
            greet_btn = gr.Button(value=i18n("submit_button"))

        with gr.Row():
            reset_btn = gr.Button("Reset Name")

        greet_btn.click(fn=add_hello_world, inputs=name_input, outputs=output_text)
        reset_btn.click(fn=lambda: i18n("john_doe"), inputs=None, outputs=name_input)

        gr.Markdown("""
        This demo shows Gradio's internationalization (i18n) functionality. 
        The interface automatically displays text in the user's browser language 
        (if available in our translations), or falls back to English.
        """)

if __name__ == "__main__":
    # pass i18n to the launch function
    demo.launch(i18n=i18n)
```

Code after:
			// Provide a no-op dispatcher for test environments
			this.dispatcher = () => {};
			return;
		}
		const { register, dispatcher } = getContext<{
			register: (
				id: number,
				set_data: (data: U & SharedProps) => void,
				get_data: Function
			) => void;
			dispatcher: Function;
		}>(GRADIO_ROOT);

		register(
			_props.shared_props.id,
			this.set_data.bind(this),
			this.get_data.bind(this)
		);

		this.dispatcher = dispatcher;

		$effect(() => {
			// Need to update the props here
			// otherwise UI won't reflect latest state from render
			for (const key in _props.shared_props) {
				if (this._is_i18n_managed(`shared.${key}`, _props.shared_props[key]))
					continue;
				// @ts-ignore i'm not doing pointless typescript gymanstics
				this.shared[key] = _props.shared_props[key];
			}
			for (const key in _props.props) {
				if (this._is_i18n_managed(`props.${key}`, _props.props[key])) continue;
				// @ts-ignore same here
				this.props[key] = _props.props[key];
			}
			register(
				_props.shared_props.id,
				this.set_data.bind(this),
				this.get_data.bind(this)
			);
			untrack(() => {
				this.shared.id = _props.shared_props.id;
			});
		});

		// retranslate props when locale changes
		if (Object.keys(this.translatable_props).length > 0) {
			locale.subscribe(() => {
				for (const [full_key, original] of Object.entries(
					this.translatable_props
				)) {