55372c8bb88563f82260530066fbb93064c3b777
home.md
| ... | ... | @@ -26,6 +26,7 @@ SAP is at the center of today’s technology revolution, developing innovations |
| 26 | 26 | * [[User Management|wiki/info/landscape/usermanagement]] |
| 27 | 27 | * [[Development Environment|wiki/info/landscape/development-environment]] |
| 28 | 28 | * [[Production Environment|wiki/info/landscape/production-environment]] |
| 29 | + * [[Internationalization (i18n)|wiki/howto/development/i18n]] |
|
| 29 | 30 | * [[Typical Development Scenarios|wiki/info/landscape/typical-development-scenarios]] |
| 30 | 31 | * [[RaceLog Tracking Server Architecture|wiki/info/landscape/server]] |
| 31 | 32 | * Environment Overview [[PDF|wiki/info/mobile/event-tracking/architecture.pdf]] | [[SVG|wiki/info/mobile/event-tracking/architecture.svg]] |
wiki/howto/development/gwt-ui-binder.md
| ... | ... | @@ -30,13 +30,13 @@ Ubilabs will deliver two versions of the site: one for use on desktops and table |
| 30 | 30 | |
| 31 | 31 | ## Internationalization (i18n) |
| 32 | 32 | |
| 33 | -We're not yet decided on how to implement i18n. GWT offers two mechanisms that seem viable, see http://www.gwtproject.org/doc/latest/DevGuideUiBinderI18n.html. We could use GWT's feature that generates the property files. The upside would be that in case of many static texts we would get a quick start. The generation of UUIDs from the original static texts additionally ensures that changes cause compile errors and hence notify us that re-translation is required, which is good. |
|
| 33 | +GWT offers two mechanisms for i18n, see [https://www.gwtproject.org/doc/latest/DevGuideUiBinderI18n.html](https://www.gwtproject.org/doc/latest/DevGuideUiBinderI18n.html) for the UI Binder approach and [https://www.gwtproject.org/doc/latest/DevGuideI18nMessages.html](https://www.gwtproject.org/doc/latest/DevGuideI18nMessages.html) for explicit message declaration. The upside of GWT's feature that generates the property files would be that in case of many static texts we would get a quick start. The generation of UUIDs from the original static texts additionally ensures that changes cause compile errors and hence notify us that re-translation is required, which is good. |
|
| 34 | 34 | |
| 35 | 35 | The downside is that redundancies across different entry points are not handled well and that the property files may not fit in well with programmatic use of those message strings. |
| 36 | 36 | |
| 37 | -Alternatively, it is possible to declare the string messages class and the method name that shall be used for the string message property. This way, we could consolidate all texts into a single message properties file which may help avoid redundancies. |
|
| 37 | +Alternatively, it is possible to declare the string messages class and the method name that shall be used for the string message property. This way, we consolidate all texts into a single message properties file which may help avoid redundancies. This is what we have decided for. Find those various ``StringMessages.java`` and corresponding ``StringMessages.properties`` in various places. |
|
| 38 | 38 | |
| 39 | -We'll probably try out both approaches in a small scale and then decide. |
|
| 39 | +More details on the i18n process, e.g., how translation is triggered, can be found [here](/wiki/howto/development/i18n). |
|
| 40 | 40 | |
| 41 | 41 | ## UI Architecture |
| 42 | 42 |
wiki/howto/development/i18n.md
| ... | ... | @@ -0,0 +1,96 @@ |
| 1 | +# Internationalization (i18n) |
|
| 2 | + |
|
| 3 | +The topic of internationalization deals largely with the translation of UI texts into different languages / locales. In this project we see three different approaches: |
|
| 4 | + |
|
| 5 | +- message strings for web user interfaces built with the Google Web Toolkit (GWT), with i18n happening on the client based, e.g., on the browser's locale |
|
| 6 | +- message strings display in the web user interface, but with the locale and message selection happening on the server side, e.g., for the Data Mining framework |
|
| 7 | +- message strings for mobile apps |
|
| 8 | + |
|
| 9 | +For all these cases, English (en) and German (de) are the development locales where development maintains the message strings. All other languages (at the time of this writing these are zh, ru, ja, es, fr, pt, it, da, sl, and cs) will be handled by SAP Language Labs (LXLabs). The process for this is explained below. |
|
| 10 | + |
|
| 11 | +## GWT UI, Messages |
|
| 12 | + |
|
| 13 | +[https://www.gwtproject.org/doc/latest/DevGuideI18nMessages.html](https://www.gwtproject.org/doc/latest/DevGuideI18nMessages.html) documents the basics. We have several such messages interfaces, such as ``com.sap.sailing.gwt.ui.client.StringMessages`` in the ``com.sap.sailing.gwt.ui`` bundle. These message files contain key/value pairs where the values may contain placeholders for parameters which have to match the corresponding method signature's parameters. The message files use the general Java properties file syntax, in particular the single-quote magic for escaping character sequences which otherwise would have special meaning. Placeholders are written as the zero-based parameter number in curly braces (``{0}``, ``{1}``, etc.). |
|
| 14 | + |
|
| 15 | +For accessing these messages in client-side GWT code, obtain an instance of the messages interface, as so: |
|
| 16 | + |
|
| 17 | +``` |
|
| 18 | + public static final StringMessages INSTANCE = GWT.create(StringMessages.class); |
|
| 19 | +``` |
|
| 20 | + |
|
| 21 | +## Backend Messages |
|
| 22 | + |
|
| 23 | +When message strings have to be translated based on a locale already in the back-end, ``com.sap.sse.i18n.ResourceBundleStringMessages`` can be used. Create one instance like this: |
|
| 24 | + |
|
| 25 | +``` |
|
| 26 | + private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/Polars_StringMessages"; |
|
| 27 | + |
|
| 28 | + sailingServerStringMessages = new ResourceBundleStringMessagesImpl( |
|
| 29 | + STRING_MESSAGES_BASE_NAME, getClassLoader(), |
|
| 30 | + StandardCharsets.UTF_8.name()); |
|
| 31 | +``` |
|
| 32 | + |
|
| 33 | +The same quoting, escaping and placeholder rules apply as for standard Java properties files and hence the GWT UI messages files. The difference, when compared to the GWT UI messages, is that there is no Java interface type that models each message as a method. Instead, the default "en" locale is then provided by a file named like the base name provided to the constructor, with the ``.properties`` suffix appended. A good place is a ``resources/`` source folder in your bundle which then contains a ``stringmessages`` sub-folder in which the ``.properties`` files reside. In the example above, the files would have paths relative to the bundle's root folder like this: ``resources/stringmessages/Polar_StringMessages.properties`` for the default "en" locale, or ``resources/stringmessages/Polar_StringMessages_es.properties`` for the Spanish locale. |
|
| 34 | + |
|
| 35 | +The string message values are obtained in the back-end code ``ResourceBundleStringMessages.get`` methods, passing the user's locale that may, e.g., be inferred through ``ProxiedRemoteServiceServlet.getClientLocale()`` when in a GWT RPC service implementation. |
|
| 36 | + |
|
| 37 | +## Mobile Apps |
|
| 38 | + |
|
| 39 | +We can distinguish three types of mobile apps that were created so far over the course of the program. We started by implementing a first native Android app (SAP Sailing Race Manager), using Java as the development language, sharing code also with the back-end logic. Two more apps followed with the same approach: the SAP Sailing Buoy Pinger and the self-tracking SAP Sail InSight app. |
|
| 40 | + |
|
| 41 | +SAP Sail InSight was then also ported to iOS, using Swift / ObjectiveC as languages. |
|
| 42 | + |
|
| 43 | +Later, SAP Sail InSight was developed again from the ground up, this time as a React Native app using TypeScript as the development language. Its naming was slightly altered into "Sail Insight (Powered by SAP)", and it went through different organizations taking care of and publishing it. |
|
| 44 | + |
|
| 45 | +All these approaches differ in how i18n is done for them. |
|
| 46 | + |
|
| 47 | +### Native Android Apps |
|
| 48 | + |
|
| 49 | +These keep their message strings in files called ``strings.xml`` under the ``res/`` folder in the respective app's root folder. They are located in directories named after the locale for which they are used. The default "en" locale uses ``values`` as the directory name, so in total ``mobile/{app-root-folder}/res/values/strings.xml``. Other locales append the locale name to the ``values`` folder name, separated by a dash. Example: ``mobile/{app-root-folder}/res/values-pt/strings.xml`` for the Portugese translations. |
|
| 50 | + |
|
| 51 | +### Old iOS App |
|
| 52 | + |
|
| 53 | +The old iOS version of SAP Sail InSight is still around in our repository. It lives under the ``ios`` root folder in our Git workspace. For each locale there is a ``*.lproj`` sub-folder in ``ios/SAPTracker/src/xcode/SAPTracker`` where the default "en" locale is represented by the ``Base.lproj`` folder, Chinese would then be ``ios/SAPTracker/src/xcode/SAPTracker/zh.lproj``, and so on. In each such ``*.lproj`` folder there are two files: ``InfoPlist.strings`` and ``Localizable.strings`` out of which the app draws the message strings to display for the user. |
|
| 54 | + |
|
| 55 | +### React Native Version of Sail Insight |
|
| 56 | + |
|
| 57 | +The primary repository for the app lives at ``trac@sapsailing.com:/home/trac/sailinsight-git``. A copy exists on Github: ``git@github.com:SailTracks/sailinsight.git``. In order to have these be subject to translation within our existing project with SAP LXLabs, we create a synchronization job that copies the message strings from the ``*.json`` files in the ``src/i18n/translations`` directory of the app repository into the equal-named folder of our default SAP Sailing Analytics repository (currently ``ssh://trac@sapsailing.com/home/trac/git``). When translation is completed, translation results need to be transferred back into the Sail Insight repository. |
|
| 58 | + |
|
| 59 | +## Triggering and Integrating Translations |
|
| 60 | + |
|
| 61 | +We entertain a Git repo clone at ``https://github.tools.sap/SAP-Sailing-Analytics/sapsailing``. When we push new commits to the ``translation`` branch of that repository (see [https://github.tools.sap/SAP-Sailing-Analytics/sapsailing/tree/translation](https://github.tools.sap/SAP-Sailing-Analytics/sapsailing/tree/translation)) then LXLabs will grab these changes in regular intervals (as of this writing typically every Friday evening) and look for changes in files that belong to any message collection. |
|
| 62 | + |
|
| 63 | +Message collections are declared in the file ``translation_v2.json`` in the root of our Git workspace. Adding new collections to this file requires us to inform LXLabs (e.g., vyacheslav.sklyarenko@sap.com, called "Slava"). They need to make the corresponding update in the so-called [Translation Enablement Workbench](https://tew.ingress.prod.lp.shoot.live.k8s-hana.ondemand.com/#/param/WzIwMiw1NiwiLyIsInRhc2tRdWV1ZSJd). |
|
| 64 | + |
|
| 65 | +During the translation process, translators may have questions regarding new or changed message strings. This will results in tasks being assigned by the Translation Enablement Workbench, and an e-mail to the assignee will result. Currently, the default assignee for these tasks is axel.uhl@sap.com. We then need to answer these questions as soon as possible to unblock the translation process so that ideally we get the translation in the same sweep as those for other languages, in the same round. |
|
| 66 | + |
|
| 67 | +When translations are done, they are pushed to the same ``translation`` branch of ``https://github.tools.sap/SAP-Sailing-Analytics/sapsailing`` by LXLabs and then usually contain the translation of all changed or added message strings. LXLabs goes by the default locale ("en") and ignores all we do in the German ("de") locale. |
|
| 68 | + |
|
| 69 | +We maintain a [Hudson build job](https://hudson.sapsailing.com/job/SAPSailingAnalytics-translation/) for the ``translation`` branch on our regular repository. Each time we receive translations back from LXLabs we first push them to the ``translation`` branch on our core repo at ``ssh://trac@sapsailing.com/home/trac/git`` and see if the Hudson job builds them without errors. This partly goes back to the times when LXLabs had issues exporting Java properties file syntax when placeholders and single-quote characters were used in the translations; a common problem in the French translations. However, this has improved massively, and we haven't seen any translation-incurred build errors in a long time. Yet, we stick to the process. |
|
| 70 | + |
|
| 71 | +Once the Hudson job for the ``translation`` branch has built the LXLabs translations OK, we merge the ``translation`` branch into our ``master`` branch, and once a good release has been obtained, roll-out to the landscape can take place. |
|
| 72 | + |
|
| 73 | +## Adding New Collections of Translatable Strings |
|
| 74 | + |
|
| 75 | +Follow the patterns you find in the ``translation_v2.json`` file at the root of our Git repository and make sure to inform LXLabs (currently vyacheslav.sklyarenko@sap.com, called "Slava"). Make sure you have your default ("en") and German ("de") locale-specific files in place and checked into Git. Once LXLabs has confirmed the creation of the new collection, push your changes to the [https://github.tools.sap/SAP-Sailing-Analytics/sapsailing/tree/translation](https://github.tools.sap/SAP-Sailing-Analytics/sapsailing/tree/translation) branch and wait for the translations to come back. |
|
| 76 | + |
|
| 77 | +## Adding Locales |
|
| 78 | + |
|
| 79 | +This comes with two aspects. |
|
| 80 | + |
|
| 81 | +As the first aspect, GWT requires us to "declare" the locales we support. We currently do this in two files which serve as the common ancestor in the GWT module inheritance hierarchy for the two major areas that contribute end user-facing entry points: |
|
| 82 | + |
|
| 83 | +- ``java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/SailingLocalesAllPermutations.gwt.xml`` |
|
| 84 | +- ``java/com.sap.sse.security.ui/src/main/resources/com/sap/sse/security/ui/SecurityLocalesAllPermutations.gwt.xml`` |
|
| 85 | + |
|
| 86 | +They both have a sibling file ``...SinglePermutation.gwt.xml`` which is used for local / fast builds where only one browser permutation for the default "en" locale is defined. |
|
| 87 | + |
|
| 88 | +The list of locales supported is specified in a line like this: |
|
| 89 | + |
|
| 90 | +``` |
|
| 91 | + <extend-property name="locale" values="en,de,zh,ru,ja,es,fr,pt,it,da,sl,cs" /> |
|
| 92 | +``` |
|
| 93 | + |
|
| 94 | +Add your locale's two-letter key to the end of this list, separated by a comma. |
|
| 95 | + |
|
| 96 | +The second aspect is to request the translation into the new locale from LXLabs (vyacheslav.sklyarenko@sap.com, called "Slava"). This typically comes at a price tag of around 5k Euro for each new language. If the cost center owner approves, LXLabs bills the language addition to that cost center, and a few weeks later the new translations will be delivered to the ``translation`` branch. |
|
| ... | ... | \ No newline at end of file |