a-b-street / abstreet

Transportation planning and traffic simulation software for creating cities friendlier to walking, biking, and public transit
https://a-b-street.github.io/docs/
Apache License 2.0
7.66k stars 340 forks source link

Localization (Translation) #695

Open KovalevArtem opened 3 years ago

KovalevArtem commented 3 years ago

It is sad that the application is only in English - I propose to translate. I am ready to help in the translation into Russian. (For example, you can use Weblate, or any other service. It is completely free for open source projects.)

image

dabreegster commented 3 years ago

Thanks for the offer to translate! I have no familiarity with how localizing software works. We have lots of strings scattered through our codebase. I'll read up on https://docs.weblate.org/en/latest/formats.html and figure out what's involved to hook everything up.

dabreegster commented 3 years ago

My understanding of the overall workflow is this:

1) In our Rust code, any hardcoded user-facing string needs to get wrapped with a macro, using something like tr 2) There are tools that scan through the source code, find all of the strings with these macros, and build up a list of things to translate. The filename and nearby comments are included for context. 3) We use something like weblate to crowd-source translations 4) Once in a while, we download a language-specific file, and put it in a place that tr can find.

https://github.com/kellpossible/cargo-i18n is another crate that helps with this process. I haven't looked into the differences between gettext, fluent, etc yet.

Some considerations:

Between A/B Street and all of the other apps, there's a huge surface area to deal with. Even inserting the tr! macros everywhere will be quite a chore without any automation.

michaelkirk commented 3 years ago

How do we choose a language at runtime? Given the use of macros, I'm guessing we produce totally different builds for different languages. This is reasonable if there's lots of strings and the number of languages grows over time.

I haven't looked too deeply at the implementation of tr!, but typically localization is a run-time thing (I've never seen the contrary). You bundle up all the translated strings with the app assets, e.g. in the same way you'd bundle up images or fonts, then the localization runtime will grab the appropriate one for your locale, and plug them into the UI.

If supporting too many languages becomes a burden on distribution size, we could package less popular translations separately or allow them to be downloaded dynamically. I'd start with just including them all to keep things simple.

We use something like weblate to crowd-source translations

There are some nice interfaces/tools like this to help translators, but it's also possible to start with just a text editor + git.

I often refer to what the Druid people are doing, since they seem to have broad experience building UI frameworks.

https://github.com/linebender/druid/blob/master/druid/src/localization.rs

(tldr; they use https://github.com/projectfluent/fluent-rs)

Whatever system we hook into, we have to make sure it doesn't depend on a native library or try to read a l18n file from disk at runtime. These won't play nice with WASM. Luckily I see some crates for embedding the strings during the build process.

Good to call out! Since the web app is especially sensitive to file size, I'm hopeful we'd also eventually have some feasible way to fetch the necessary localization file as a separate resource request like we do with maps.

KovalevArtem commented 3 years ago

@comradekingu Do you have any ideas on how to make localization as simple and effective as possible?

comradekingu commented 3 years ago

As long as you end up with for example GNU gettext PO/POT files, that has great support in Weblate, and can handle quirks in different languages. https://docs.weblate.org/en/latest/formats.html?highlight=gettext#translation-types-capabilities