[FOLIO-546] design i18n for services and data Created: 06/Apr/17 Updated: 12/Nov/18 Resolved: 12/Apr/17 |
|
| Status: | Closed |
| Project: | FOLIO |
| Components: | None |
| Affects versions: | None |
| Fix versions: | None |
| Type: | Umbrella | Priority: | P3 |
| Reporter: | Jakub Skoczen | Assignee: | Jakub Skoczen |
| Resolution: | Won't Do | Votes: | 0 |
| Labels: | sprint12 | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | 1 hour | ||
| Original estimate: | Not Specified | ||
| Issue links: |
|
||||||||
| Sprint: | |||||||||
| Description |
|
Here's a proposal for i18ing data and services in FOLIO, handling UI string bundles is discussed last. JSON Schema Schemas are extended so that all scalar string values that should support i18n are turned into a new type called i18nString, with the following definition: i18nString.schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"patternProperties": {
"^[a-z][a-z]$": {"type": "string"}
}
}
We would then use the schema in place of strings as such: ... "displayName": { "$ref": "i18nString"} ... RAML In order to filter what languages should be included in the output the service will investigate the Accept-Language request header, eg. GET /users/1234 HTTP/1.1 Accept-Language: en, da and reply with:
Content-Language: en, da
{
"displayName": {
"en": "Copenhagen",
"da": "København"
}
}
Searching/filtering with CQL For collection services that include CQL filtering/searching capability matching should be performed on all stored i18n values by default, so: displayName == "Copenhagen" would return results no matter which internationalized value of displayName matched. Although, what would be included in the body/response still depends on the value of Content-Language header. To control what internationalized values are used for matching the following query should be specified: displayName ==/lang=da "Copenhagen" String bundles String bundles for things like UI labels that come included with the apps will most likely be pre-loaded into a centralized service. Still, the same general approach described above can be used when programing the API for that centralized translation service. |
| Comments |
| Comment by Mike Taylor [ 06/Apr/17 ] |
|
That mostly looks good, except that I can't see why the client would ever want to have data returned in more than one language. Can we interpret the Accept-Language header as an ordered list of preferences? Then if I send Accept-Language: en, da and the service has English data, it can just return
Content-Language: en
{
"displayName": "Copenhagen"
}
and the client's life doesn't get more complicated than it is now. |
| Comment by Jakub Skoczen [ 07/Apr/17 ] |
|
The client will want the data returned in more than one language when editing the internationalized labels that it maintains on it's own. E.g a Danish library might want to see two input fields when editing Patron Groups, one for the Danish version and one for the English version. This is unrelated to currently selected display language for the UI/client. |
| Comment by Mike Taylor [ 07/Apr/17 ] |
|
I see. So this is not how you perceive regular day-to-day requests proceeding. |
| Comment by Marc Johnson [ 07/Apr/17 ] |
|
What scope/degree of the properties on a resource are you envisaging being able to be expressed in multiple languages (I haven't been involved in the SIG conversations, so am not aware of whether this has been answered)? It seems to me that for these kinds of resources, many of the properties are likely to be displayed and hence would need to take this form? Hugs |
| Comment by Jakub Skoczen [ 07/Apr/17 ] |
|
Marc Johnson This is focused on a general approach for providing just the ability. I will be talking to Filip about how exactly this would be used in the UI. And which fields will potentially needs this capability. |
| Comment by shale99 [ 09/Apr/17 ] |
|
some thoughts... on both UI and API consumers (i think they should behave the same) I like the idea of the UI requesting an i18n / l10n bundle via an API for a specific language and locally replacing placeholders in the front end code. In my opinion, this also makes sense to an API user - where they can request a bundle for a specific module in a specific language. module_name.patron_group.on_campus=On Campus using an api that returns a module specific bundle will allow us to implement a single API for both UI and API consumers - while leaving the display-ablity to the consumer (whether that be an editing app or the UI itself). is there a need to require a module to return specific key / value pairs? wouldnt a returned bundle for a specific module in a specific language suffice? when writing the UI i believe most frameworks works with bundles, i think that when editing , well, this will be via a UI interface as well, so wouldnt an editing app (which could be module agnostic) have it easier to request a bundle from a module and based on metadata in the bundle + key + values - be able to display an editing interface? and then just call a save() API to persist the updated bundle. |
| Comment by shale99 [ 09/Apr/17 ] |
|
as for the json schema - this looks good to me, i think we only need one returned language value though, this will allow returning a request for GET() items in french, with , for example a material type code 12345567 (not book |
| Comment by Mike Taylor [ 10/Apr/17 ] |
Is "module_name" a placeholder here, and the other components literals? If I understood right, then, the general pattern would be:
and the specific example would be:
Is that it? |
| Comment by Jakub Skoczen [ 10/Apr/17 ] |
|
shale99 I don't think a single centralized "translation" service will not cut it (if that's what you are indeed proposing) as it is largely incompatible with our microservices-like approach. E.g adding or removing a new patron group would effectively be a transaction between the "patron groups" endpoint and the "translations" service. Multiply this by the overall number of all endpoints and you end up with a system where a single service is required to complete any given request. As I mentioned in the description, there is a place for a centralized service with "static" string bundles (UI labels, messages, etc). Those would get updated when apps are installed/upgraded or when a new string bundle (e.g created by a tenant for a niche language) is explicitly imported into the system. They would also be queries once at the start of the user "sessions" (e.g when user logs in to the UI) As for why we need to be able to request a list of language rather than just one at a time – see my reply to Mike's comment above. |
| Comment by Julian Ladisch [ 10/Apr/17 ] |
|
The FOLIO 2018 V1 document lists these use cases: "Ability to supply translations for library-configured content (locations, libraries, permissions, patron group etc.)." However, there won't be much more use cases. This is a very low priority issue and has been excluded from the requirements of version 1. It is very low priority because it is usually done by simply concatenating the names, for example "København/Copenhagen", or even used without translation because it is a small number of names and everybody knowns what they mean. |
| Comment by Jakub Skoczen [ 10/Apr/17 ] |
|
Agree, this seems to be of a low-priority for V1 so the main purpose is to establish that we can extend the services with a relative easy to provide i18n for values of data elements. Also, it seems that for V1 we would only support a single local/language for tenant thus the need for "Ability..." would be relatively of low priority. |
| Comment by Julian Ladisch [ 10/Apr/17 ] |
|
I think that the multi-language schema and api capability proposed by this issue is overkill for the long run as well. Most institutions will never use them. Those that may want to use them can use the translation capabilities instead. Translations of commonly used permission group names and patron group names can be provided by the FOLIO project. An institution that have specific group names or need location or library name translations may create an institution specific language translation file for each module where this is needed and upload those string bundles to the system because these names rarely change. However, this will work for FOLIO specific interfaces only. Standard APIs like NCIP do not support multiple languages and need to use the concatentation of the translations as described above. In the rare cases where there is really a need to provide several languages at the same time these translations can be retrieved by requesting them one by one. I don't see the need to introduce an additional level of complexity (array of translations) in most APIs that won't be used and doesn't have advantages. |
| Comment by shale99 [ 13/Apr/17 ] |
|
basically, i am missing the concept for the end game, what will this look like or is there a different line of how translations are going to work |