<!-- 
RSS generated by JIRA (1001.0.0-SNAPSHOT#100246-sha1:7a5c50119eb0633d306e14180817ddef5e80c75d) at Thu Feb 08 23:06:36 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>FOLIO Jira</title>
    <link>https://folio-org.atlassian.net</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>1001.0.0-SNAPSHOT</version>
        <build-number>100246</build-number>
        <build-date>07-02-2024</build-date>
    </build-info>

<item>
            <title>[FOLIO-546] design i18n for services and data</title>
                <link>https://folio-org.atlassian.net/browse/FOLIO-546</link>
                <project id="10290" key="FOLIO">FOLIO</project>
                    <description>&lt;p&gt;Here&apos;s a proposal for i18ing data and services in FOLIO, handling UI string bundles is discussed last.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;JSON Schema&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Schemas are extended so that all scalar string values that should support i18n are turned into a new type called &lt;tt&gt;i18nString&lt;/tt&gt;, with the following definition:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeHeader panelHeader&quot; style=&quot;border-bottom-width: 1px;&quot;&gt;&lt;b&gt;i18nString.schema&lt;/b&gt;&lt;/div&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-javascript&quot;&gt;
{
  &lt;span class=&quot;code-quote&quot;&gt;&quot;$schema&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;http:&lt;span class=&quot;code-comment&quot;&gt;//json-schema.org/draft-04/schema#&quot;&lt;/span&gt;,
&lt;/span&gt;  &lt;span class=&quot;code-quote&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;object&quot;&lt;/span&gt;,
  &lt;span class=&quot;code-quote&quot;&gt;&quot;patternProperties&quot;&lt;/span&gt;: {
    &lt;span class=&quot;code-quote&quot;&gt;&quot;^[a-z][a-z]$&quot;&lt;/span&gt;: {&lt;span class=&quot;code-quote&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;string&quot;&lt;/span&gt;}
  }
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We would then use the schema in place of strings as such:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-javascript&quot;&gt;
...
  &lt;span class=&quot;code-quote&quot;&gt;&quot;displayName&quot;&lt;/span&gt;: { &lt;span class=&quot;code-quote&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;i18nString&quot;&lt;/span&gt;}
...
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;RAML&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;In order to filter what languages should be included in the output the service will investigate the &lt;tt&gt;Accept-Language&lt;/tt&gt; request header, eg.&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
GET /users/1234 HTTP/1.1
Accept-Language: en, da
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and reply with:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
Content-Language: en, da

{
  &lt;span class=&quot;code-quote&quot;&gt;&quot;displayName&quot;&lt;/span&gt;: {
     &lt;span class=&quot;code-quote&quot;&gt;&quot;en&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;Copenhagen&quot;&lt;/span&gt;,
     &lt;span class=&quot;code-quote&quot;&gt;&quot;da&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;K&#248;benhavn&quot;&lt;/span&gt;
   }
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Searching/filtering with CQL&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;For collection services that include CQL filtering/searching capability matching should be performed on all stored i18n values by default, so:&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;displayName == &quot;Copenhagen&quot;&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;would return results no matter which internationalized value of &lt;tt&gt;displayName&lt;/tt&gt; matched. Although, what would be included in the body/response still depends on the value of &lt;tt&gt;Content-Language&lt;/tt&gt; header.&lt;/p&gt;

&lt;p&gt;To control what internationalized values are used for matching the following query should be specified:&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;displayName ==/lang=da &quot;Copenhagen&quot;&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;String bundles&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;</description>
                <environment></environment>
        <key id="80260">FOLIO-546</key>
            <summary>design i18n for services and data</summary>
                <type id="10006" iconUrl="https://folio-org.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10307?size=medium">Umbrella</type>
                                            <priority id="10002" iconUrl="https://dev.folio.org/assets/jira-priority/jira-p3.svg">P3</priority>
                        <status id="6" iconUrl="https://folio-org.atlassian.net/images/icons/statuses/closed.png" description="The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.">Closed</status>
                    <statusCategory id="3" key="done" colorName="green"/>
                                    <resolution id="10000">Won&apos;t Do</resolution>
                                                        <assignee accountid="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d">Jakub Skoczen</assignee>
                                                                <reporter accountid="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d">Jakub Skoczen</reporter>
                                    <labels>
                            <label>sprint12</label>
                    </labels>
                <created>Thu, 6 Apr 2017 11:12:39 +0000</created>
                <updated>Mon, 12 Nov 2018 14:23:28 +0000</updated>
                            <resolved>Wed, 12 Apr 2017 12:24:20 +0000</resolved>
                                                                        <due></due>
                            <votes>0</votes>
                                    <watches>7</watches>
                                                    <timespent seconds="3600">1 hour</timespent>
                                <comments>
                                                            <comment id="191833" author="5bffed52a1b46046f530c8f7" created="Thu, 6 Apr 2017 11:28:31 +0000"  >&lt;p&gt;That mostly looks good, except that I can&apos;t see why the client would ever want to have data returned in more than one language. Can we interpret the &lt;tt&gt;Accept-Language&lt;/tt&gt; header as an ordered list of preferences? Then if I send &lt;tt&gt;Accept-Language: en, da&lt;/tt&gt; and the service has English data, it can just return&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
Content-Language: en
{
  &lt;span class=&quot;code-quote&quot;&gt;&quot;displayName&quot;&lt;/span&gt;: &lt;span class=&quot;code-quote&quot;&gt;&quot;Copenhagen&quot;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and the client&apos;s life doesn&apos;t get more complicated than it is now.&lt;/p&gt;</comment>
                                                            <comment id="191834" author="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d" created="Fri, 7 Apr 2017 10:02:54 +0000"  >&lt;p&gt;The client will want the data returned in more than one language when editing the internationalized labels that it maintains on it&apos;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.&lt;/p&gt;</comment>
                                                            <comment id="191835" author="5bffed52a1b46046f530c8f7" created="Fri, 7 Apr 2017 10:09:17 +0000"  >&lt;p&gt;I see. So this is not how you perceive regular day-to-day requests proceeding.&lt;/p&gt;</comment>
                                                            <comment id="191836" author="63e2a2771b13d42998e4e706" created="Fri, 7 Apr 2017 10:33:23 +0000"  >&lt;p&gt;&lt;a href=&quot;https://folio-org.atlassian.net/secure/ViewProfile.jspa?accountId=557058%3Ab8e64633-1f7c-402d-9caf-9959a5ba5d0d&quot; class=&quot;user-hover&quot; rel=&quot;557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d&quot; data-account-id=&quot;557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d&quot; accountid=&quot;557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d&quot; rel=&quot;noreferrer&quot;&gt;Jakub Skoczen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What scope/degree of the properties on a resource are you envisaging being able to be expressed in multiple languages (I haven&apos;t been involved in the SIG conversations, so am not aware of whether this has been answered)?&lt;/p&gt;

&lt;p&gt;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?&lt;/p&gt;

&lt;p&gt;Hugs&lt;/p&gt;</comment>
                                                            <comment id="191837" author="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d" created="Fri, 7 Apr 2017 10:40:41 +0000"  >&lt;p&gt;&lt;a href=&quot;https://folio-org.atlassian.net/secure/ViewProfile.jspa?accountId=63e2a2771b13d42998e4e706&quot; class=&quot;user-hover&quot; rel=&quot;63e2a2771b13d42998e4e706&quot; data-account-id=&quot;63e2a2771b13d42998e4e706&quot; accountid=&quot;63e2a2771b13d42998e4e706&quot; rel=&quot;noreferrer&quot;&gt;Marc Johnson&lt;/a&gt; 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.&lt;/p&gt;</comment>
                                                            <comment id="191838" author="712020:32bb56ac-50e7-4787-b4af-ed3089d9401c" created="Sun, 9 Apr 2017 04:41:12 +0000"  >&lt;p&gt;some thoughts... on both UI and API consumers (i think they should behave the same)&lt;/p&gt;

&lt;p&gt;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.&lt;br/&gt;
I havent checked how react works with this, but creating a bundle for a module would&lt;br/&gt;
1. allow the UI to request this once and then do local lookups - i believe the keys in an i18n bundle should be namespaced, so that patron_group keys. will look something like &lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;module_name.patron_group.on_campus=On Campus

&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

</comment>
                                                            <comment id="191839" author="712020:32bb56ac-50e7-4787-b4af-ed3089d9401c" created="Sun, 9 Apr 2017 08:57:02 +0000"  >&lt;p&gt;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 &lt;img class=&quot;emoticon&quot; src=&quot;/images/icons/emoticons/smile.png&quot; height=&quot;16&quot; width=&quot;16&quot; align=&quot;absmiddle&quot; alt=&quot;&quot; border=&quot;0&quot;/&gt; )  as &quot;Livre&quot; in the item itself instead of Book&lt;/p&gt;</comment>
                                                            <comment id="191840" author="5bffed52a1b46046f530c8f7" created="Mon, 10 Apr 2017 10:29:36 +0000"  >&lt;p&gt;&lt;a href=&quot;https://folio-org.atlassian.net/secure/ViewProfile.jspa?accountId=712020%3A32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; class=&quot;user-hover&quot; rel=&quot;712020:32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; data-account-id=&quot;712020:32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; accountid=&quot;712020:32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; rel=&quot;noreferrer&quot;&gt;shale99&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;module_name.patron_group.on_campus=On Campus&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Is &quot;module_name&quot; a placeholder here, and the other components literals? If I understood right, then, the general pattern would be:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;module_name.resource_name.value_name=text&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;and the specific example would be:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;users.patron_group.on_campus=On Campus&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Is that it?&lt;/p&gt;</comment>
                                                            <comment id="191841" author="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d" created="Mon, 10 Apr 2017 10:54:17 +0000"  >&lt;p&gt;&lt;a href=&quot;https://folio-org.atlassian.net/secure/ViewProfile.jspa?accountId=712020%3A32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; class=&quot;user-hover&quot; rel=&quot;712020:32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; data-account-id=&quot;712020:32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; accountid=&quot;712020:32bb56ac-50e7-4787-b4af-ed3089d9401c&quot; rel=&quot;noreferrer&quot;&gt;shale99&lt;/a&gt; I don&apos;t think a single centralized &quot;translation&quot; service will not cut it (if that&apos;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 &quot;patron groups&quot; endpoint and the &quot;translations&quot; 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.&lt;/p&gt;

&lt;p&gt;As I mentioned in the description, there is a place for a centralized service with &quot;static&quot; 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 &quot;sessions&quot; (e.g when user logs in to the UI)&lt;/p&gt;

&lt;p&gt;As for why we need to be able to request a list of language rather than just one at a time &amp;#8211; see my reply to Mike&apos;s comment above.&lt;/p&gt;</comment>
                                                            <comment id="191842" author="5ee89462f7aa140abd82d11d" created="Mon, 10 Apr 2017 14:35:25 +0000"  >&lt;p&gt;The FOLIO 2018 V1 document lists these use cases: &quot;Ability to supply translations for library-configured content (locations, libraries, permissions, patron group etc.).&quot; However, there won&apos;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 &quot;K&#248;benhavn/Copenhagen&quot;, or even used without translation because it is a small number of names and everybody knowns what they mean.&lt;/p&gt;</comment>
                                                            <comment id="191843" author="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d" created="Mon, 10 Apr 2017 14:50:22 +0000"  >&lt;p&gt;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 &quot;Ability...&quot; would be relatively of low priority.&lt;/p&gt;</comment>
                                                            <comment id="191844" author="5ee89462f7aa140abd82d11d" created="Mon, 10 Apr 2017 15:05:01 +0000"  >&lt;p&gt;I think that the multi-language schema and api capability proposed by this issue is overkill for the long run as well.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;I don&apos;t see the need to introduce an additional level of complexity (array of translations) in most APIs that won&apos;t be used and doesn&apos;t have advantages.&lt;/p&gt;</comment>
                                                            <comment id="191845" author="712020:32bb56ac-50e7-4787-b4af-ed3089d9401c" created="Thu, 13 Apr 2017 07:10:09 +0000"  >
&lt;p&gt;basically, i am missing the concept for the end game, &lt;br/&gt;
other then &lt;br/&gt;
1. translations of course are a must&lt;br/&gt;
2. the ui will want to work with bundles&lt;br/&gt;
3. modules may have the same names for labels so should be name-spaced&lt;/p&gt;

&lt;p&gt;what will this look like &lt;br/&gt;
for static and dynamic labels - &lt;br/&gt;
1. how do we except users to edit / persist static - dynamic labels - separate interfaces? , a single interface?&lt;br/&gt;
2. how do we store them - all labels stored in their respective modules with an api to retrieve / save?&lt;br/&gt;
3. if a single UI interface for editing - how does the single interface retrieve ALL available labels from a module? is there a crud to get all dynamic labels and another api to get all static labels from a module - if so, why are two needed?&lt;br/&gt;
4. can a api comsumer request a result set in a specific language, which will return translated cv&apos;s?&lt;/p&gt;


&lt;p&gt;or is there a different line of how translations are going to work&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10000">
                    <name>Blocks</name>
                                            <outwardlinks description="blocks">
                                        <issuelink>
            <issuekey id="79440">FOLIO-535</issuekey>
        </issuelink>
                            </outwardlinks>
                                                        </issuelinktype>
                    </issuelinks>
                <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10000" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummarycf">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10019" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|hzxmdz:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10020" key="com.pyxis.greenhopper.jira:gh-sprint">
                        <customfieldname>Sprint</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        <customfield id="customfield_10024" key="com.atlassian.jira.ext.charting:firstresponsedate">
                        <customfieldname>[CHART] Date of First Response</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>Thu, 6 Apr 2017 11:28:31 +0000</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10025" key="com.atlassian.jira.ext.charting:timeinstatus">
                        <customfieldname>[CHART] Time in Status</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                    </customfields>
    </item>
</channel>
</rss>