ipm
ipm copied to clipboard
How to define localized strings?
I've figured out how to define localized error messages using LOC resource in module.xml
<Resource Name="My.Errors.LOC"/>
And supporting file src/My/Errors.xml
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="IRIS" version="26">
<Document name="My.Errors.LOC">
<MsgFile Language="en">
<MsgDomain Domain="MyErr">
<Message Id="CustomError">Value %1 is invalid</Message>
</MsgDomain>
</MsgFile>
</Document>
</Export>
Which when loaded generates localize/My/MyErrrors.xml
file in the working copy and My.Errors
include routine (read only):
ROUTINE My.Errors [Type=INC]
#define MyErrCustomError "<MyErr>CustomError"
Which I can include and use as $$$ERROR($$$MyErrCustomError, 42)
Is there a ZPM way to do this for non-error strings such as form labels?
Just curious, how, you would like to use it? With $$$Text, or some other way? those LOC files are loaded as my localization files and goes to ^IRIS.Msg
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="IRIS" version="26">
<Document name="demo.LOC">
<MsgFile Language="en">
<MsgDomain Domain="myapp">
<Message Id="Information">Some Information</Message>
<Message Id="Description">Some Description</Message>
</MsgDomain>
</MsgFile>
</Document>
</Export>
This LOC file will generate
^IRIS.Msg("myapp","en","Description")="Some Description"
^IRIS.Msg("myapp","en","Information")="Some Information"
And this already can be used in Application in some way.
correct, using $$$Text — what does the module.xml look like to load that demo.LOC resource? Where in the working copy do I put the file?
On Sep 15, 2021, at 6:08 AM, Dmitry Maslennikov @.***> wrote:
Just curious, how, you would like to use it? With $$$Text, or some other way? those LOC files are loaded as my localization files and goes to ^IRIS.Msg
This LOC file will generate Some Information Some Description ^IRIS.Msg("myapp","en","Description")="Some Description" ^IRIS.Msg("myapp","en","Information")="Some Information" And this already can be used in Application in some way.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.
I don't know so much about $$$Text, but, what I found is, that it always generates new info in ^IRIS.Msg
So, this usage off macros
$$$Text("@Information@Some Information","myapp","en")
will generate the same data
^IRIS.Msg("myapp","en","Description")="Some Description"
with ZPM, suppose, I'd like to support two languages, and I've created two files en.xml
and ru.xml
With the content similar to above. I placed both files in folder src/localize
(localize
is hardcoded for LOC files, which expected under the SourcesRoot
)
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="loc-test.ZPM">
<Module>
<Name>loc-test</Name>
<Version>1.0.0</Version>
<Packaging>module</Packaging>
<SourcesRoot>src</SourcesRoot>
<Resource Name="en.loc"/>
<Resource Name="ru.loc"/>
<Resource Name="demo.mac"/>
</Module>
</Document>
</Export>
And after install I've got this
^IRIS.Msg("myapp","en","Description")="Some Description"
^IRIS.Msg("myapp","en","Information")="Some Information"
^IRIS.Msg("myapp","ru","Description")="Описание"
^IRIS.Msg("myapp","ru","Information")="Информация"
But, if I would have this piece of code in my demo.mac
Write $$$Text("@Information@Info","myapp","en")
It will override localization from LOC files, and I found only one way, to get the correct localization, is to read it directly, something like this
Write !,$$$GetAppMessage("en", "myapp", "Information", "Info")
arguments are: language, domain, id, default
And this will read the correct value, which was in LOC files
So, probably, the best way would be to just override $$$Text macro, to be it like $$$GetAppMessage
and if we consider /src as a root for module.xml resources, what is the folder for loc.xml files? is it should be in /loc ?
On Wed, Sep 15, 2021 at 8:35 AM Dmitry Maslennikov @.***> wrote:
I don't know so much about $$$Text, but, what I found is, that it always generates new info in ^IRIS.Msg
So, this usage off macros @.***@Some Information","myapp","en") will generate the same data ^IRIS.Msg("myapp","en","Description")="Some Description"
with ZPM, suppose, I'd like to support two languages, and I've created two files en.xml and ru.xml With the content similar to above. I placed both files in folder src/localize (localize is hardcoded for LOC files, which expected under the SourcesRoot)
<Module> <Name>loc-test</Name> <Version>1.0.0</Version> <Packaging>module</Packaging> <SourcesRoot>src</SourcesRoot> <Resource Name="en.loc"/> <Resource Name="ru.loc"/> <Resource Name="demo.mac"/> </Module>
And after install I've got this
^IRIS.Msg("myapp","en","Description")="Some Description"
^IRIS.Msg("myapp","en","Information")="Some Information"
^IRIS.Msg("myapp","ru","Description")="Описание"
^IRIS.Msg("myapp","ru","Information")="Информация"
But, if I would have this piece of code in my demo.mac
Write @.***@Info","myapp","en")
It will override localization from LOC files, and I found only one way, to get the correct localization, is to read it directly, something like this
Write !,$$$GetAppMessage("en", "myapp", "Information", "Info")
arguments are: language, domain, id, default
And this will read the correct value, which was in LOC files
So, probably, the best way would be to just override $$$Text macro, to be it like $$$GetAppMessage
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/intersystems-community/zpm/issues/258#issuecomment-919979198, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVHEP33PBFLSFSF5OSISDTUCCHINANCNFSM5EBWPCZQ .
At the moment localize
inside src
folder if it's configured
inside /localize folder right?
On Wed, Sep 15, 2021 at 9:01 AM Dmitry Maslennikov @.***> wrote:
At the moment localize inside src folder if it's configured
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/intersystems-community/zpm/issues/258#issuecomment-919997143, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVHEP3HWYANGTWH7FFTIGTUCCKJPANCNFSM5EBWPCZQ .
e.g. /src/localize/en.xml
On Wed, Sep 15, 2021 at 9:06 AM Евгений Шваров @.***> wrote:
inside /localize folder right?
On Wed, Sep 15, 2021 at 9:01 AM Dmitry Maslennikov < @.***> wrote:
At the moment localize inside src folder if it's configured
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/intersystems-community/zpm/issues/258#issuecomment-919997143, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVHEP3HWYANGTWH7FFTIGTUCCKJPANCNFSM5EBWPCZQ .
yes
would be great to document it.
On Wed, Sep 15, 2021 at 9:07 AM Dmitry Maslennikov @.***> wrote:
yes
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/intersystems-community/zpm/issues/258#issuecomment-920002234, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVHEP2IAV6AQYUABN5FXMTUCCLBTANCNFSM5EBWPCZQ .
When I add the src/localize/en.xml
and corresponding <Resource Name="en.loc"/>
to the module.xml ZPM fails with a class not found error for my original My.Errors.LOC
Project structure And module.xml
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="loc-test.ZPM">
<Module>
<Name>loc-test</Name>
<Version>1.0.0</Version>
<Packaging>module</Packaging>
<SourcesRoot>src</SourcesRoot>
<Resource Name="My.Errors.LOC"/>
<Resource Name="en.loc"/>
<Resource Name="ru.loc"/>
<Resource Name="demo.mac"/>
</Module>
</Document>
</Export>
Just to note, that this functionality is going from InterSystems realization just for HealthShare, and have not been used or reviewed since that. There are a few points here that look strange to me.
So, I would only look at this, as to how we can improve it, to make it useful for us.
And any suggestions will be helpful
Btw, my current module, after installing generate a few more XML files in localize
folder at the root of the project, ignoring src
.
excerpt from my verbose log of installation
[loc-test] Activate START
Exporting messages for 'My.Errors' domain(s) to /opt/repo/loc-test/localize/MyErrors.xml
Exporting messages for 'myapp' domain(s) to /opt/repo/loc-test/localize/en.xml
It's like, exporting localization from developer's. Domain name is not supposed to have dots, so, for My.Errors.LOC
, it exports domain MyErrors to MyErrors.xml
So, I think as a first improvement, I would suggest do not use SourcesRoot
for localization files and place them in the root and keep localize
. But, not sure, what to do with export localization after compile
Totally agree we need to pull this out of src
, and also feel ZPM should never write to the working copy unless in developer mode. I also think it is important to leverage paradigms that already are in widespread use (e.g. $$$Text, %MessageDictionary).
Here is an idea for your consideration. First the module.xml
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="zpm-sample.ZPM">
<Module>
<Name>zpm-sample</Name>
<Version>0.1.0+SNAPSHOT</Version>
<Packaging>module</Packaging>
<SourcesRoot>src</SourcesRoot>
<Resource Name="MyApp.PKG"/>
<!-- module message domain(s) for use with $$$Text -->
<Domain Name="MyApp"/>
<!-- module error domain(s) for use with $$$ERROR -->
<Domain Name="MyAppErr" IsError="1"/>
<!-- main language to use during compilation -->
<Language Name="en" Default="1"/>
<!-- other supported languages -->
<Language Name="ru"/>
<Language Name="fr"/>
</Module>
</Document>
</Export>
File structure:
zpm-sample
├── lang
│ ├── en.xml
│ ├── fr.xml
│ └── ru.xml
├── src
│ └── MyApp
│ └── Main.cls
└── module.xml
So the language files default to <working copy>/lang/*.xml
. We could provide a LanguageRoot
setting and/or a Language/@Path
override too. I feel lang
is more appropriate here than localize
. Each language file contains one or more domains:
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="IRIS" version="26">
<Document name="en.LOC">
<MsgFile Language="en">
<!-- messages -->
<MsgDomain Domain="MyApp">
<Message Id="Greeting">Hello</Message>
</MsgDomain>
<!-- errors -->
<MsgDomain Domain="MyAppErr">
<Message Id="InvalidScope">The scope '%1' is invalid.</Message>
</MsgDomain>
</MsgFile>
</Document>
</Export>
I'm not sure if we need the Export/Document
wrapper, whatever is easiest to implement with existing tools is fine for a little extra boilerplate.
From a ZPM lifecycle point of view the import would set the domain default language ^IRIS.Msg(<domain>)
to the default specified in the module.xml
. Post compile if in developer mode that language file should be updated to pickup any changes for commit to source control. The module author would execute zpm "compile my-app"
as needed (but at least prior to submitting a pull-request) to automatically update the language xml file.
The final piece is the error message dictionary. Here the developer manually maintains the error domain messages. The Domain/@IsError
setting tells ZPM to generate an include file after the import phase to ensure successful compile. When developer updates the error domain, a zpm "import my-app"
would make the any new error macros available. Alternatively the module author could omit the IsError
flag and maintain the INC file(s) by hand - benefits of that approach would be keeping the INC under source control, having the ability of which errors to expose via macro, and backward compatibility with code bases prior to the ZPM lifecycle.
PS: Lots of good info here: https://community.intersystems.com/post/localization-cach%C3%A9-dbms
A brief note on history here, the .LOC document type was intended to take some practices from HS dev around error message localization (having them in an XML file ingested during build processes) and bring the source into the DB as a first-class citizen via %Studio.AbstractDocument so that it could be edited alongside other code.
The Export/Document wrapper is just how XML export of a %Studio.AbstractDocument works (which is the same as XML export of anything else) - I believe this could just as easily be UDL (same as everything else), but haven't tried that before.
Export during the Activate phase was to support some of the build processes in HS but I would agree that this shouldn't happen unless specifically requested. (There's a resource processor class, LocalizationExport, that should be used to explicitly request this export if needed.)
I'm a fan of @mvhenderson 's ideas above.
Note: loading the module with -dev
creates an entry in ^Sources
for the generated localize; don't think we'll need that so should be removed when refactoring to move localize
out of src
.
^Sources=""
^Sources("ZPM","*","NoFolders")=1
^Sources("ZPM","zpm-sample")=$c(0)_"/iris/"
^Sources("cls","MyApp.")=$c(0)_"/iris/src/"
^Sources("loc","en")=$c(0)_"/iris/src/localize/"