Skip to content

Ensure translations work as expected #11049

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Apr 24, 2025
Merged

Ensure translations work as expected #11049

merged 21 commits into from
Apr 24, 2025

Conversation

hannahblair
Copy link
Collaborator

@hannahblair hannahblair commented Apr 17, 2025

Description

There are two key i18n fixes in this PR:

  1. When testing custom internationalisation I noticed that translation in the footer wasn't actually working as expected because of how we're getting the current locale. It seems the reason why is because getLocaleFromNavigator() returns BCP 47 language tags (like "en-US", "de-DE") while our translation files use simple language codes ("en", "de"). I've added a normalisation func to handle this.
Screenshot 2025-04-17 at 17 18 22
  1. Values that come from the backend used to get translated without a problem because we didn't have namespaced key values in our translation files, so Submit as a value in gr.Button used to get translated without an issue. Now, we have Submit under the common namespace like "common": { "submit": "Submit" }. So gradio.i18n("Submit") will just return Submit because it can't find it in en.json without the common prefix. Strings that are hardcoded and don't come from the backend are obviously unaffected and work fine.

To fix this, during i18n setup, we now iterate through all language files and compile a Set (all_common_keys) containing every key defined within any common namespace (e.g., "common.submit", "common.flag").

Fallback flow:

  • It first attempts a direct translation of the input value
  • If that fails, it normalises the input value (lowercase). It then iterates through the all_common_keys set. For each key (like "common.flag"), it extracts the base name ("flag"). If the normalised input value matches the extracted base key name, it uses the full common key ("common.flag") to attempt translation in the current locale. If a successful translation is found via this key-name matching, it's returned
  • If no match or translation occurs, the original input value is used as a final fallback

If the user uses their own value which isn't in the namespace then this obviously wont get translated, unless they use the up and coming gr.i18n() func!

We do need to check that we have all our default values in the common namespace now.

🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is an existing issue for this change. If not, please create an issue before you create this PR, unless the fix is very small.

Not adhering to this guideline will result in the PR being closed.

Testing and Formatting Your Code

  1. PRs will only be merged if tests pass on CI. We recommend at least running the backend tests locally, please set up your Gradio environment locally and run the backed tests: bash scripts/run_backend_tests.sh

  2. Please run these bash scripts to automatically format your code: bash scripts/format_backend.sh, and (if you made any changes to non-Python files) bash scripts/format_frontend.sh

@hannahblair hannahblair changed the title Ensure Ensure translations work as expected Apr 17, 2025
@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Apr 17, 2025

🪼 branch checks and previews

Name Status URL
Spaces ready! Spaces preview
Storybook ready! Storybook preview
🦄 Changes detecting...

Install Gradio from this PR

pip install https://gradio-pypi-previews.s3.amazonaws.com/fa5a3bd25d9fb96d7d9158cd82936d362773e618/gradio-5.25.2-py3-none-any.whl

Install Gradio Python Client from this PR

pip install "gradio-client @ git+https://github.com/gradio-app/gradio@fa5a3bd25d9fb96d7d9158cd82936d362773e618#subdirectory=client/python"

Install Gradio JS Client from this PR

npm install https://gradio-npm-previews.s3.amazonaws.com/fa5a3bd25d9fb96d7d9158cd82936d362773e618/gradio-client-1.14.2.tgz

Use Lite from this PR

<script type="module" src="https://gradio-lite-previews.s3.amazonaws.com/fa5a3bd25d9fb96d7d9158cd82936d362773e618/dist/lite.js""></script>

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Apr 17, 2025

🦄 change detected

This Pull Request includes changes to the following packages.

Package Version
@gradio/core patch
@self/storybook patch
gradio patch
  • Maintainers can select this checkbox to manually select packages to update.

With the following changelog entry.

Ensure translations work as expected

Maintainers or the PR author can modify the PR title to modify this entry.

Something isn't right?

  • Maintainers can change the version label to modify the version bump.
  • If the bot has failed to detect any changes, or if this pull request needs to update multiple packages to different versions or requires a more comprehensive changelog entry, maintainers can update the changelog file directly.

@hannahblair hannahblair marked this pull request as ready for review April 22, 2025 14:04
@abidlabs
Copy link
Member

Just want to clarify one thing: I thought only strings that are hardcoded into the UI are translated? Is it the case that other strings are automatically translated as well if they happen to match one of the UI strings?

E.g. let's say I have gr.Textbox(value="Submit", placeholder="Submit") -- since Submit is part of the list of words we internationalize (in the context of the gr.Button component), will it get internationalized for the Textbox's value and label as well? I don't think that should be the case for several reasons:

  • The same word in English can mean different things depending on the context. We know how to translate "submit" as in "submitting a button" into different languages, but that translation may not make sense for a Textbox's placeholder if "Submit" is being used in a different sense of the word here
  • It prevents users from overriding this behavior. The correct way to internationalize the textbox placeholder or value would be to use the custom gr.i18n class, but if we are autotranslating, then users will not be able to control this behavior.
  • Auto-translation is particularly problematic for any value that goes to the backend. Is it the translated value that goes to the backend? the original value?

@freddyaboulton freddyaboulton added v: patch A change that requires a patch release t: fix A change that implements a fix labels Apr 22, 2025
@hannahblair
Copy link
Collaborator Author

hannahblair commented Apr 22, 2025

@abidlabs I understand the confusion! Let me clarify.

E.g. let's say I have gr.Textbox(value="Submit", placeholder="Submit") -- since Submit is part of the list of words we internationalize (in the context of the gr.Button component), will it get internationalized for the Textbox's value and label as well?

Yes, it would be - this was actually the behaviour prior to our translation change, so it's technically a regression fix. I see what you're saying about contextual translation, that could be an edge case.

It prevents users from overriding this behavior. The correct way to internationalize the textbox placeholder or value would be to use the #11047, but if we are autotranslating, then users will not be able to control this behavior.

The custom i18n should always take precedence over our core translations, though i haven't tested this in the PR for that

Auto-translation is particularly problematic for any value that goes to the backend. Is it the translated value that goes to the backend? the original value?

Great point! I'm pretty sure the value is never directly affected by translation, it's purely visual - but I'd like to double check that


See this demo (in french)

with gr.Blocks() as demo:
    gr.Textbox()
    gr.Button()
    gr.UploadButton()
    gr.Dropdown()
    gr.Checkbox()
    gr.Slider()
    gr.Markdown()

This is what it looks like in main vs this PR

main pr
Screenshot 2025-04-23 at 01 10 18 Screenshot 2025-04-23 at 01 10 45

There are still some translation gaps in this demo, but my thoughts are that using those components without any configuration (so gradio's default values used instead) should mean that it will also handle translation for users in my app as well for a seamless user experience. right now we have a lot of inconsistencies which feels janky and broken.

This all being said, it's a relatively niche problem and custom i18n will fix any annoyances people may have :)

Copy link
Collaborator

@freddyaboulton freddyaboulton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good @hannahblair !

Copy link
Member

@pngwn pngwn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me, I tested and although I am far from and expert, it looked good!

Thanks for tackling this one @hannahblair!

@abidlabs
Copy link
Member

Amazing will merge this in so that we can review the other one!

@abidlabs abidlabs merged commit 8d2aa3e into main Apr 24, 2025
24 checks passed
@abidlabs abidlabs deleted the browser-locale branch April 24, 2025 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
t: fix A change that implements a fix v: patch A change that requires a patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants