Wikidata / SQID

A tool to analyse, browse and query Wikidata
http://tools.wmflabs.org/sqid/
Apache License 2.0
84 stars 17 forks source link

i18n structure #65

Closed arsylum closed 5 years ago

arsylum commented 8 years ago

currently i18n is only instantiated when a controller depends on it. Eg http://tools.wmflabs.org/sqid/#/?lang=de doesn't have the intended effect, http://tools.wmflabs.org/sqid/#/view?lang=de does. However navigating back and forth from there to http://tools.wmflabs.org/sqid/#/view (or similar, stripping the lang param) swaps the language back to en since ViewController calls View.updateLang() and that's the default when no value is given.

What adds to the confusion is that $translationProvider.preferredLanguage('en') is set, which i18n doesn't really seem to take into account but happens to be the same default value. pascalprecht.translate also provides functionality to derive a fitting lang from browser locale settings, which we might want to use.

It's all a bit confusing for me, probably because there is logic handling the (static) interface language and for dynamically retrieved label data. My proposal is to try leverage language handling into a more powerful position. Possibly a "global setup wrapper" controller or something?

mkroetzsch commented 8 years ago

Our message translation framework, Angular Translate, keeps the state (configured language). This state will affect all places where messages are used, even if they are used in a view without the controller detecting the language. Of course, it would be better if the language assumed by our i18n moule would always be in synch with the language used for the UI, but I would consider this as a temporary issue, which occurs only for incompletely i18ned views.

Is it possible to make all controllers handle the lang parameter consistently in an elegant way? Some kind of super-controller that they all "inherit" from?

There are two possibly related problems:

arsylum commented 8 years ago

I'm confused. Isn't the menu already properly i18ned? For me it seems to be that way.

The $translate service keeps the state (now even across different browsing sessions via cookies or local storage) but i18n should take this into account when for instance i18n.setLanguage(null); is called like it happens on every instantiation of the ViewController without a ?lang param in the url. Because as of now i18n will simply execute $translate.use('en'); in that case.

I don't really understand yet why the controllers have to be involved anyway when $translate basically provides a set of system wide localized messages with the directives and filters to fill them in the templates. Hence I feel like I'm still missing some parts here.

mkroetzsch commented 8 years ago

If the controllers are not involved, who will interpret the lang=foo URL parameter?

As for the menu, it uses messages, but I ma not sure if this usage of angular translate is correct, since they are outside of the controller that actually sets the language. It seems to work, but is this the proper way of doing it?

arsylum commented 8 years ago

$translate is already functional after the .config(['$translateProvider'... before any controllers are instantiated.

I am sure there are plenty of ways but I don't have a very good overview myself yet. Actually I was gonna propose angular.module('classBrowserApp').run(['$route', function($route) { // do what needs to be done }]); but that actually runs only once on hard refreshes. The $location service might do the trick though. I need to read into it a little bit..

arsylum commented 8 years ago

Picking up the i18n part from #67:

Since I feel a bit of confusion and lack of common vision about our localisation design I will try to describe how I currently picture it conceptually and hopefully ease further communication a bit.

I see our current localisation module as a two layered system, where we have the higher level i18n service, and angular-translate as part of the foundation. View logic should talk to the i18n service which is facing the application and also proxies to $translate for UI translation. But while somehow 'in charge' of l10n affairs the i18n.service shouldn't reinvent on things angular-translate already has implemented.

we need to distinguish the case "no language set, defaulting to English" from the case "language set to English by the user"

I still don't understand why is that. From the code I can only see this playing a role in forging the lang parameter into URLs. But that to me is a very tricky trade-off situation on it's own. I agree that it should be possible to include language configuration in an URL pointer, to share a specific state of the application, on the other hand I can imagine that in majority of cases it is preferable to use the language requested by the user agent on an initial page load. Other than for sharing links it seems very unnecessary to me to keep language state in the URL when we actually have a service that manages that. So ideally it could be optional to have a language enforcing URL to a certain page or state but then again, having configurable URLs seems too bulky UX wise. In a little modal share widget it could possibly work though.

My main trouble here I think is, that I do not know which decisions in the implementation were made for which reasons, but there are a few things that strike me as counter intuitive. Like having controllers manually request i18nized application URLs, while we probably could also have a catch-all approach and keep the links in the controllers (and templates, and directives, ...) simple.

Oh, and an option to actually set the language is also something that should be added to the interface at some point. I don't see it as a high priority yet though.

mkroetzsch commented 8 years ago

The distinction of "defaulting to en" and "explicitly requested en" (possibly even if the browser is set to something else) is important for generating external links, which also distinguish the two options ("use browser default" vs. "define your own language"). See #41.

Inside of our own application, we have some freedom to modify how we manage language settings. The only thing there is that language should be preserved, even when opening a new tab. So one would need a cookie-based approach rather than a javascript-based one (e.g., the approach we use to persist Browse settings does not work across tabs, but this is acceptable; changing languages would not be so nice). Using URL parameters also simplifies link sharing to show others the results in a specific language. If you remove lang from URLs, you would probably want to have permalink options for every view that people would have to use instead if they want to share what they see. Maybe these options could be part of the footer or menu, so that one does not have to add them to all views.

A language selector widget would be nice, yes. That's a separate task for a future branch.

arsylum commented 8 years ago

Remembering language setting across tabs is already taken care of via localStorage (or cookie as fallback) by angular-translate storage extension and is included in the current state of the refactwo branch (see). For me that seems to work pretty well.

But for external and sharing URLs I find it rather difficult to decide on a sensible behavior. My point being that by sharing a view one might not necessarily want the receiver(s) to see the exact same output, but just the same content "in a language they understand". I wouldn't say enforcing a set language preference by default is a bad approach, but for me this is a challenging issue that warrants further discussion.

mkroetzsch commented 8 years ago

Re multi-tab language setting: good

Re preserving language for external URLs or not: What you say is exactly the point. This is why we have both behaviours: either you set your language explicitly, or you only link the content (without a specific language).

There is no standard behaviour on other sites either. Reasonator also preserves the language setting for external URLs, and it keeps the chosen language in the URL if set explicitly. In contrast, Wikidata does not preserve the uselang parameter or setting if you continue browsing from a given site (or maybe it only does this when not logged in with an own language setting; not sure).

I think the issue that our URLs show different languages to each user is acceptable, esp. if we have a working language selector soon. Then users can just change into whatever they prefer at any time.

The issue with the external links is more tricky. It seems to be a nice feature to send users to the "right" language directly if they have manually picked a language in SQID that is not their browser default. I don't think there is any good reason to give this up from a user perspective. However, #41 states that users do not want the default guess to be made permanent in this way.

Interestingly, it seems that the refactwo code does exactly this, even if it lost the lang parameter from the URL: if you have not set the language explicitly, it does not use a parameter for external links; if you have set it (even if it got lost again), it will use it in external links. The only concern I have there is that this introduces hidden state information that might be confusing to people. Again, a language selector might help to clarify the current setting (even if not in the URL).