Page MenuHomePhabricator

[Spike] How should i18n work for Vue.js search?
Closed, ResolvedPublicSpike

Description

The new search experience should work everywhere both for users and developers. If users can't use our components, they won't be used. If developers can't reuse our components, they won't be used. To this end, the internationalization strategy for components should work robustly and with as few dependencies on the MediaWiki ecosystem as possible (in production and during development). This task is to identify the options available and their tradeoffs.

This task is focused on identifying an appropriate internationalization project infrastructure. For example, mw.msg(). T249300 focuses on components themselves and is distinct.

Acceptance criteria

  • Different Vue.js internationalization options are identified including Santhosh's vue-banana-i18n, Roan's fork, and the standard recommend by Vue School, vue-i18n.
  • The tradeoffs for each solution are enumerated herein.
    • vue-i18n@8.17.6: 25.2 kB minified / 7.5 kB minified + gzipped
      • vue-i18n uses a different localization message syntax. Custom formatting is supported but may not be practical given wiki markup.
    • vue-banana-i18n@1.2.1: 39 kB minified / 15.1 kB minified + gzipped
      • vue-banana-i18n fully supports MW localization syntax and has no MediaWiki dependencies.
      • Supports localizing strings and Vue directives like v-i18n:search_results="[10]". See readme for details.
    • Roan's fork
      • Implicit dependency on mw.msg().
      • Otherwise the same as vue-banana-i18n.
    • Component properties
      • Pushes internationalization out into the consuming application for the scope of search.
  • A decision for the approach to take is made and a task is created.

Open questions

  • mw.msg()-based solutions have a dependency on jQuery? Should this be considered an isolated exception to avoiding jQuery usage in shared components? Does this mean i18n support won't be very good outside of MW?
  • How is WMDE approaching i18n and is it working well?

Event Timeline

Restricted Application changed the subtype of this task from "Task" to "Spike". · View Herald TranscriptApr 3 2020, 7:12 PM
Niedzielski renamed this task from [Spike] How should i18n work? to [Spike] How should i18n work for Vue.js search?.Apr 5 2020, 4:23 PM

I don't expect base UI components having any non-configurable messages. So, all of the messages will be passed as props. For example button labels. But the LTR, RTL support is built into the framework. You don't need CSSJanus - This is achieved by using logical directions(start, end) instead of left, right in grid. This also means, you can change the direction of a rendered page without reloading with new css from resource loader. there is only one stylesheet for RTL or LTR. This contributed to the size of grid css, but as you observed, it is well compressible. I will write a storybook story illustrating this.

If the search form is loaded in Vector and passed the UI language's strings, do we need anything else? For example, something like:

import { MwTypeaheadSearch } from '@wikimedia/mw-vue-components';

new Vue( {
  data: { msgContaining: mw.msg( 'searchsuggest-containing' ) },
  render: MwTypeaheadSearch
} ).$mount( '#app' )

We cannot use vue-i18n because it uses a completely new localization message syntax. MediaWiki uses a powerful localization syntax based on wiki markup. This format is implmented in

  1. Our PHP Localization Code
  2. mw.message library in Mediawiki core javscript
  3. jquery.i18n as standalone jquery library
  4. banana-i18n as framework independent javascript library(vue-banana-i18n is a vue wrapper for it)

Roan's implementation and vue-banana-i18n exposes same apis and directives. Only difference is Roan's implmentation uses mw.msg for actual i18n work and hence it is dependent on Mediawiki. vue-banana-i18n is mediawiki independent library - may be more important if we want to build systems decoupled from mediawiki. As a matter of fact, Content translation uses vue-banana-i18n.

If the search form is loaded in Vector and passed the UI language's strings, do we need anything else? For example, something like:

import { MwTypeaheadSearch } from '@wikimedia/mw-vue-components';

new Vue( {
  data: { msgContaining: mw.msg( 'searchsuggest-containing' ) },
  render: MwTypeaheadSearch
} ).$mount( '#app' )

This should be enough for a very simple usecase that is closely coupled with mw.message RL module. But if you want to use i18n in template strings, then the above mentioned implmentations provide directives such as <div v-i18n:searchsuggest-containing/> or even a little more sophisticated vue directives to pass parameters. And make sure the messages are reactive to locale, message key and message params.

Thank you, @santhosh. Very helpful. I've tried to summarize your feedback in the description. If I understand you and the ContentTranslation's base library approach correctly, passing in properties is best for primitive components like Buttons, Inputs, and so forth. The more complex or application-specific a composition of components becomes, the more likely that full localization support will be needed. If this is true, I recommend we try to pursue pass in strings for search from the Vector skin for the scope of this project.

The new search experience should work everywhere both for users and developers

What does everywhere mean here?

mw.msg()-based solutions have a dependency on jQuery? Should this be considered an isolated exception to avoiding jQuery usage in shared components? Does this mean i18n support won't be very good outside of MW?

FWIW I've just been using vanilla mediawiki for mw.msg. (L68). Outside MediaWiki it just reads directly from an imported JSON. That only becomes less useful if your messages contain wikitext or parameters (although latter is easy to workaround).

The i18n requirements of the search based on the mocks look pretty small to me as most of the data we need to i18n will come from the API itself. Is this really a blocker for the search work? Can't we just use the mediawiki msg function and collect information on what doesn't work for us? jQuery is already a given in a mediawiki environment and we're already building for that environment. Provided the component library takes parameters for its messages we can completely descope this for now and keep the payload down (which seems like an important goal).

I don't expect base UI components having any non-configurable messages. So, all of the messages will be passed as props. For example button labels. But the LTR, RTL support is built into the framework. You don't need CSSJanus - This is achieved by using logical directions(start, end) instead of left, right in grid. This also means, you can change the direction of a rendered page without reloading with new css from resource loader. there is only one stylesheet for RTL or LTR. This contributed to the size of grid css, but as you observed, it is well compressible. I will write a storybook story illustrating this.

@santhosh As I'm more interested in the UI/CSS rendering behaviour than the localized messages itself. Do you have already code examples to show the functionality? Curious how strong the framework really is here, CSSJanus has been developed over several years to achieve wide property and combination cases support.

If the search form is loaded in Vector and passed the UI language's strings, do we need anything else? For example, something like:

import { MwTypeaheadSearch } from '@wikimedia/mw-vue-components';

new Vue( {
  data: { msgContaining: mw.msg( 'searchsuggest-containing' ) },
  render: MwTypeaheadSearch
} ).$mount( '#app' )

@santhosh As I'm more interested in the UI/CSS rendering behaviour than the localized messages itself. Do you have already code examples to show the functionality? Curious how strong the framework really is here, CSSJanus has been developed over several years to achieve wide property and combination cases support.

  • Storybook showing LTR, RTL on the fly flipping.
  • source code of the grid that takes care of layouting and spacing
  • A video illustrating on the fly flipping F31857662

This is not an attempt to re-implement everything that CSSJanus does in SCSS or LESS. IMO, many of the things that CSSJanus does becomes irrelavant if we approach the problem differently. CSSJanus is from a time period every developer write layout css for every element they add to screen. In modern UI frameworks, semantic classes takes care of styling and achieves consistancy. In otherwords, no developer write padding, margin and such css styles. Intead they use abstractions of these styling described using a semantic class. These classes can be low level abstractions like ma-2(add 2 unit margin in all sides), ps-4(Add 4 unit padding at start of the element-it becomes left or right depending directionality). It can be high level abstractions like page-title, page-image, warning etc based on a design vocabulary clearly defined in a stylebook. Declarative and Reactive UI development like this will make many problems we had in the past obsolete. This is not a new concept. Famous reactive UI frameworks already do LTR/RTL handling in this way. Example: Vuetify.

The grid in the framework is based on flexbox which already supports LTR and RTL. CSS logical direction properties are coming to browsers but not all of them supported yet. We can take advantage of whatever supported. For others a rooting on [dir=rtl] will help to write RTL specific code. A good thing about the above mentioned semantic classes and declarative UI building is, you don't have to repeat it everywhere.

This code is still evolving, but my intention is to untangle it from a server side css flipping system and make completely browser side and make use of many new features modern browsers give. This will definitely require help from @Volker_E and others.

As far as I understand it, for the purposes of Vue.js search we will only need to pass in strings from Vector and can defer additional i18n complexity. Flipping will also be necessary and we'll take an approach similar to what @santhosh has outlined above.

message passing looks good to me 👍 @Niedzielski I noticed part of the acceptance criteria is to create a task for the implementation. Not sure if this is still needed, but lmk if it is and I'm happy to create one. Signing off for now

nray subscribed.